From 58e02fd0353b00402e47d8cc452fa7ff17fe20a0 Mon Sep 17 00:00:00 2001 From: rudy Date: Mon, 3 Jan 2022 11:05:20 +0100 Subject: [PATCH] feat(Testlib): lib for testing libs generated by concretecompiler Closes #201 --- .gitignore | 3 + compiler/Makefile | 8 +- compiler/include/concretelang/Support/Jit.h | 2 + .../include/concretelang/TestLib/Arguments.h | 105 ++ .../concretelang/TestLib/DynamicLambda.h | 123 ++ .../concretelang/TestLib/DynamicModule.h | 33 + .../concretelang/TestLib/dynamicArityCall.h | 1468 +++++++++++++++++ .../TestLib/genDynamicArityCall.py | 6 + compiler/lib/CMakeLists.txt | 1 + compiler/lib/TestLib/Arguments.cpp | 161 ++ compiler/lib/TestLib/CMakeLists.txt | 16 + compiler/lib/TestLib/DynamicLambda.cpp | 224 +++ compiler/lib/TestLib/DynamicModule.cpp | 61 + compiler/src/CMakeLists.txt | 1 + compiler/tests/CMakeLists.txt | 1 + compiler/tests/TestLib/CMakeLists.txt | 24 + compiler/tests/TestLib/out/.keep | 0 compiler/tests/TestLib/testlib_unit_test.cpp | 241 +++ compiler/tests/unittest/end_to_end_jit_test.h | 23 +- 19 files changed, 2489 insertions(+), 12 deletions(-) create mode 100644 compiler/include/concretelang/TestLib/Arguments.h create mode 100644 compiler/include/concretelang/TestLib/DynamicLambda.h create mode 100644 compiler/include/concretelang/TestLib/DynamicModule.h create mode 100644 compiler/include/concretelang/TestLib/dynamicArityCall.h create mode 100644 compiler/include/concretelang/TestLib/genDynamicArityCall.py create mode 100644 compiler/lib/TestLib/Arguments.cpp create mode 100644 compiler/lib/TestLib/CMakeLists.txt create mode 100644 compiler/lib/TestLib/DynamicLambda.cpp create mode 100644 compiler/lib/TestLib/DynamicModule.cpp create mode 100644 compiler/tests/TestLib/CMakeLists.txt create mode 100644 compiler/tests/TestLib/out/.keep create mode 100644 compiler/tests/TestLib/testlib_unit_test.cpp diff --git a/.gitignore b/.gitignore index 9431c7506..e595d0aa4 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ _build/ # macOS .DS_Store + + +compiler/tests/TestLib/out/ diff --git a/compiler/Makefile b/compiler/Makefile index ff16c0d84..19fb7fd26 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -69,12 +69,18 @@ test-check: concretecompiler file-check not test-python: python-bindings concretecompiler PYTHONPATH=${PYTHONPATH}:$(BUILD_DIR)/tools/concretelang/python_packages/concretelang_core LD_PRELOAD=$(BUILD_DIR)/lib/libConcretelangRuntime.so pytest -vs tests/python -test: test-check test-end-to-end-jit test-python support-unit-test +test: test-check test-end-to-end-jit test-python support-unit-test testlib-unit-test test-dataflow: test-end-to-end-jit-dfr test-end-to-end-jit-auto-parallelization # unit-test +testlib-unit-test: build-testlib-unit-test + $(BUILD_DIR)/bin/testlib_unit_test + +build-testlib-unit-test: build-initialized + cmake --build $(BUILD_DIR) --target testlib_unit_test + support-unit-test: build-support-unit-test $(BUILD_DIR)/bin/support_unit_test diff --git a/compiler/include/concretelang/Support/Jit.h b/compiler/include/concretelang/Support/Jit.h index b5aea676c..db4f9a30e 100644 --- a/compiler/include/concretelang/Support/Jit.h +++ b/compiler/include/concretelang/Support/Jit.h @@ -15,6 +15,8 @@ namespace mlir { namespace concretelang { +size_t bitWidthAsWord(size_t exactBitWidth); + /// JITLambda is a tool to JIT compile an mlir module and to invoke a function /// of the module. class JITLambda { diff --git a/compiler/include/concretelang/TestLib/Arguments.h b/compiler/include/concretelang/TestLib/Arguments.h new file mode 100644 index 000000000..85cd6996b --- /dev/null +++ b/compiler/include/concretelang/TestLib/Arguments.h @@ -0,0 +1,105 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#ifndef CONCRETELANG_TESTLIB_ARGUMENTS_H +#define CONCRETELANG_TESTLIB_ARGUMENTS_H + +#include "concretelang/ClientLib/ClientParameters.h" +#include "concretelang/ClientLib/KeySet.h" + +namespace mlir { +namespace concretelang { + +class DynamicLambda; + +class Arguments { +public: + Arguments(KeySet &keySet) : currentPos(0), keySet(keySet) { + keySet.setRuntimeContext(context); + } + + ~Arguments(); + + // Create EncryptedArgument that use the given KeySet to perform encryption + // and decryption operations. + static std::shared_ptr create(KeySet &keySet); + + // Add a scalar argument. + llvm::Error pushArg(uint64_t arg); + + // Add a vector-tensor argument. + llvm::Error pushArg(std::vector arg); + + template llvm::Error pushArg(std::array arg) { + return pushArg(8, (void *)arg.data(), {size}); + } + + // Add a matrix-tensor argument. + template + llvm::Error pushArg(std::array, size0> arg) { + return pushArg(8, (void *)arg.data(), {size0, size1}); + } + + // Add a rank3 tensor. + template + llvm::Error pushArg( + std::array, size1>, size0> arg) { + return pushArg(8, (void *)arg.data(), {size0, size1, size2}); + } + + // Generalize by computing shape by template recursion + + // Set a argument at the given pos as a 1D tensor of T. + template llvm::Error pushArg(T *data, int64_t dim1) { + return pushArg(data, llvm::ArrayRef(&dim1, 1)); + } + + // Set a argument at the given pos as a tensor of T. + template + llvm::Error pushArg(T *data, llvm::ArrayRef shape) { + return pushArg(8 * sizeof(T), static_cast(data), shape); + } + + llvm::Error pushArg(size_t width, void *data, llvm::ArrayRef shape); + + // Push the runtime context to the argument list, this must be called + // after each argument was pushed. + llvm::Error pushContext(); + + template + llvm::Error pushArgs(Arg0 arg0, OtherArgs... others) { + auto err = pushArg(arg0); + if (err) { + return err; + } + return pushArgs(others...); + } + + llvm::Error pushArgs() { return pushContext(); } + +private: + friend DynamicLambda; + template + friend llvm::Expected invoke(DynamicLambda &lambda, + const Arguments &args); + llvm::Error checkPushTooManyArgs(); + + // Position of the next pushed argument + size_t currentPos; + std::vector preparedArgs; + + // Store allocated lwe ciphertexts (for free) + std::vector allocatedCiphertexts; + // Store buffers of ciphertexts + std::vector ciphertextBuffers; + + KeySet &keySet; + RuntimeContext context; +}; + +} // namespace concretelang +} // namespace mlir + +#endif diff --git a/compiler/include/concretelang/TestLib/DynamicLambda.h b/compiler/include/concretelang/TestLib/DynamicLambda.h new file mode 100644 index 000000000..aa8fe7e72 --- /dev/null +++ b/compiler/include/concretelang/TestLib/DynamicLambda.h @@ -0,0 +1,123 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#ifndef CONCRETELANG_TESTLIB_DYNAMIC_LAMBDA_H +#define CONCRETELANG_TESTLIB_DYNAMIC_LAMBDA_H + +#include "concretelang/ClientLib/ClientParameters.h" +#include "concretelang/ClientLib/KeySet.h" +#include "concretelang/ClientLib/KeySetCache.h" +#include "concretelang/TestLib/Arguments.h" +#include "concretelang/TestLib/DynamicModule.h" + +namespace mlir { +namespace concretelang { + +template struct MemRefDescriptor; + +template +llvm::Expected invoke(DynamicLambda &lambda, const Arguments &args) { + // compile time error if used + using COMPATIBLE_RESULT_TYPE = void; + return (Result)( + COMPATIBLE_RESULT_TYPE)0; // invoke does not accept this kind of Result +} + +template <> +llvm::Expected invoke(DynamicLambda &lambda, + const Arguments &args); + +template <> +llvm::Expected> +invoke>(DynamicLambda &lambda, const Arguments &args); + +template <> +llvm::Expected>> +invoke>>(DynamicLambda &lambda, + const Arguments &args); + +template <> +llvm::Expected>>> +invoke>>>(DynamicLambda &lambda, + const Arguments &args); + +class DynamicLambda { +private: + template + llvm::Expected> createArguments(Args... args) { + if (keySet == nullptr) { + return StreamStringError("keySet was not initialized"); + } + auto arg = Arguments::create(*keySet); + auto err = arg->pushArgs(args...); + if (err) { + return StreamStringError(llvm::toString(std::move(err))); + } + return arg; + } + +public: + static llvm::Expected load(std::string funcName, + std::string outputLib); + + static llvm::Expected + load(std::shared_ptr module, std::string funcName); + + template + llvm::Expected call(Args... args) { + auto argOrErr = createArguments(args...); + if (!argOrErr) { + return argOrErr.takeError(); + } + auto arg = argOrErr.get(); + return invoke(*this, *arg); + } + + llvm::Error generateKeySet(llvm::Optional cache = llvm::None, + uint64_t seed_msb = 0, uint64_t seed_lsb = 0); + +protected: + template + friend llvm::Expected invoke(DynamicLambda &lambda, + const Arguments &args); + + template + llvm::Expected> + invokeMemRefDecriptor(const Arguments &args); + + ClientParameters clientParameters; + std::shared_ptr keySet; + void *(*func)(void *...); + // Retain module and open shared lib alive + std::shared_ptr module; +}; + +template +class TypedDynamicLambda : public DynamicLambda { + +public: + static llvm::Expected> + load(std::string funcName, std::string outputLib) { + auto lambda = DynamicLambda::load(funcName, outputLib); + if (!lambda) { + return lambda.takeError(); + } + return TypedDynamicLambda(*lambda); + } + + llvm::Expected call(Args... args) { + return DynamicLambda::call(args...); + } + + // TODO: check parameter types + TypedDynamicLambda(DynamicLambda &lambda) : DynamicLambda(lambda) { + // TODO: add static check on types vs lambda inputs/outpus + } +}; + +} // namespace concretelang +} // namespace mlir + +#endif diff --git a/compiler/include/concretelang/TestLib/DynamicModule.h b/compiler/include/concretelang/TestLib/DynamicModule.h new file mode 100644 index 000000000..9f59c35a9 --- /dev/null +++ b/compiler/include/concretelang/TestLib/DynamicModule.h @@ -0,0 +1,33 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#ifndef CONCRETELANG_TESTLIB_DYNAMIC_MODULE_H +#define CONCRETELANG_TESTLIB_DYNAMIC_MODULE_H + +#include "concretelang/ClientLib/ClientParameters.h" + +namespace mlir { +namespace concretelang { + +class DynamicModule { +public: + ~DynamicModule(); + static llvm::Expected> + open(std::string libraryPath); + +private: + llvm::Error loadClientParametersJSON(std::string path); + llvm::Error loadSharedLibrary(std::string path); + +private: + std::vector clientParametersList; + void *libraryHandle; + + friend class DynamicLambda; +}; + +} // namespace concretelang +} // namespace mlir +#endif diff --git a/compiler/include/concretelang/TestLib/dynamicArityCall.h b/compiler/include/concretelang/TestLib/dynamicArityCall.h new file mode 100644 index 000000000..2a4a68240 --- /dev/null +++ b/compiler/include/concretelang/TestLib/dynamicArityCall.h @@ -0,0 +1,1468 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#ifndef CONCRETELANG_TESTLIB_DYNAMIC_ARITY_CALL_H +#define CONCRETELANG_TESTLIB_DYNAMIC_ARITY_CALL_H + +#include +#include + +namespace mlir { +namespace concretelang { + +template +Res call(Res (*func)(void *...), std::vector args) { + switch (args.size()) { + // generated part: see genDynamicArityCall.py + // TODO C17++: https://en.cppreference.com/w/cpp/utility/apply + case 1: + return func(args[0]); + case 2: + return func(args[0], args[1]); + case 3: + return func(args[0], args[1], args[2]); + case 4: + return func(args[0], args[1], args[2], args[3]); + case 5: + return func(args[0], args[1], args[2], args[3], args[4]); + case 6: + return func(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + case 8: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7]); + case 9: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8]); + case 10: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9]); + case 11: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10]); + case 12: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11]); + case 13: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12]); + case 14: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13]); + case 15: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14]); + case 16: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15]); + case 17: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16]); + case 18: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17]); + case 19: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18]); + case 20: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19]); + case 21: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20]); + case 22: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21]); + case 23: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22]); + case 24: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23]); + case 25: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24]); + case 26: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25]); + case 27: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26]); + case 28: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27]); + case 29: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28]); + case 30: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29]); + case 31: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30]); + case 32: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31]); + case 33: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32]); + case 34: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33]); + case 35: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34]); + case 36: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35]); + case 37: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36]); + case 38: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37]); + case 39: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38]); + case 40: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39]); + case 41: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40]); + case 42: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41]); + case 43: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42]); + case 44: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43]); + case 45: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44]); + case 46: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45]); + case 47: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46]); + case 48: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47]); + case 49: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48]); + case 50: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49]); + case 51: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50]); + case 52: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51]); + case 53: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52]); + case 54: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53]); + case 55: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54]); + case 56: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55]); + case 57: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56]); + case 58: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57]); + case 59: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58]); + case 60: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59]); + case 61: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60]); + case 62: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61]); + case 63: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62]); + case 64: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63]); + case 65: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60], + args[61], args[62], args[63], args[64]); + case 66: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60], + args[61], args[62], args[63], args[64], args[65]); + case 67: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60], + args[61], args[62], args[63], args[64], args[65], args[66]); + case 68: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67]); + case 69: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68]); + case 70: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69]); + case 71: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70]); + case 72: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60], + args[61], args[62], args[63], args[64], args[65], args[66], + args[67], args[68], args[69], args[70], args[71]); + case 73: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60], + args[61], args[62], args[63], args[64], args[65], args[66], + args[67], args[68], args[69], args[70], args[71], args[72]); + case 74: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73]); + case 75: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74]); + case 76: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75]); + case 77: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76]); + case 78: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77]); + case 79: + return func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], + args[7], args[8], args[9], args[10], args[11], args[12], + args[13], args[14], args[15], args[16], args[17], args[18], + args[19], args[20], args[21], args[22], args[23], args[24], + args[25], args[26], args[27], args[28], args[29], args[30], + args[31], args[32], args[33], args[34], args[35], args[36], + args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], + args[49], args[50], args[51], args[52], args[53], args[54], + args[55], args[56], args[57], args[58], args[59], args[60], + args[61], args[62], args[63], args[64], args[65], args[66], + args[67], args[68], args[69], args[70], args[71], args[72], + args[73], args[74], args[75], args[76], args[77], args[78]); + case 80: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79]); + case 81: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80]); + case 82: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81]); + case 83: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82]); + case 84: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83]); + case 85: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84]); + case 86: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85]); + case 87: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86]); + case 88: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87]); + case 89: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88]); + case 90: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89]); + case 91: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90]); + case 92: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91]); + case 93: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92]); + case 94: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93]); + case 95: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94]); + case 96: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95]); + case 97: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96]); + case 98: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97]); + case 99: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98]); + case 100: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99]); + case 101: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100]); + case 102: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101]); + case 103: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102]); + case 104: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103]); + case 105: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104]); + case 106: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105]); + case 107: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106]); + case 108: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107]); + case 109: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108]); + case 110: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109]); + case 111: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110]); + case 112: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111]); + case 113: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112]); + case 114: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113]); + case 115: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114]); + case 116: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115]); + case 117: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116]); + case 118: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117]); + case 119: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118]); + case 120: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119]); + case 121: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120]); + case 122: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120], args[121]); + case 123: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120], args[121], args[122]); + case 124: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120], args[121], args[122], + args[123]); + case 125: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120], args[121], args[122], + args[123], args[124]); + case 126: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120], args[121], args[122], + args[123], args[124], args[125]); + case 127: + return func( + args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], + args[8], args[9], args[10], args[11], args[12], args[13], args[14], + args[15], args[16], args[17], args[18], args[19], args[20], args[21], + args[22], args[23], args[24], args[25], args[26], args[27], args[28], + args[29], args[30], args[31], args[32], args[33], args[34], args[35], + args[36], args[37], args[38], args[39], args[40], args[41], args[42], + args[43], args[44], args[45], args[46], args[47], args[48], args[49], + args[50], args[51], args[52], args[53], args[54], args[55], args[56], + args[57], args[58], args[59], args[60], args[61], args[62], args[63], + args[64], args[65], args[66], args[67], args[68], args[69], args[70], + args[71], args[72], args[73], args[74], args[75], args[76], args[77], + args[78], args[79], args[80], args[81], args[82], args[83], args[84], + args[85], args[86], args[87], args[88], args[89], args[90], args[91], + args[92], args[93], args[94], args[95], args[96], args[97], args[98], + args[99], args[100], args[101], args[102], args[103], args[104], + args[105], args[106], args[107], args[108], args[109], args[110], + args[111], args[112], args[113], args[114], args[115], args[116], + args[117], args[118], args[119], args[120], args[121], args[122], + args[123], args[124], args[125], args[126]); + default: + assert(false); + } +} + +} // namespace concretelang +} // namespace mlir + +#endif diff --git a/compiler/include/concretelang/TestLib/genDynamicArityCall.py b/compiler/include/concretelang/TestLib/genDynamicArityCall.py new file mode 100644 index 000000000..231303d47 --- /dev/null +++ b/compiler/include/concretelang/TestLib/genDynamicArityCall.py @@ -0,0 +1,6 @@ +# Part of the Concrete Compiler Project, under the BSD3 License with Zama Exceptions. +# See https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license information. + +for i in range(128): + args = ','.join(f'args[{j}]' for j in range(i)) + print(f' case {i}: return func({args});') diff --git a/compiler/lib/CMakeLists.txt b/compiler/lib/CMakeLists.txt index e35d64627..96829a24b 100644 --- a/compiler/lib/CMakeLists.txt +++ b/compiler/lib/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(Support) add_subdirectory(Runtime) add_subdirectory(ClientLib) add_subdirectory(Bindings) +add_subdirectory(TestLib) # CAPI needed only for python bindings if (CONCRETELANG_BINDINGS_PYTHON_ENABLED) diff --git a/compiler/lib/TestLib/Arguments.cpp b/compiler/lib/TestLib/Arguments.cpp new file mode 100644 index 000000000..6d7625d5f --- /dev/null +++ b/compiler/lib/TestLib/Arguments.cpp @@ -0,0 +1,161 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#include "concretelang/TestLib/Arguments.h" +#include "concretelang/Support/CompilerEngine.h" +#include "concretelang/Support/Error.h" +#include "concretelang/Support/Jit.h" + +namespace mlir { +namespace concretelang { + +Arguments::~Arguments() { + for (auto ct : allocatedCiphertexts) { + int err; + free_lwe_ciphertext_u64(&err, ct); + } + for (auto ctBuffer : ciphertextBuffers) { + free(ctBuffer); + } +} + +std::shared_ptr Arguments::create(KeySet &keySet) { + auto args = std::make_shared(keySet); + return args; +} + +llvm::Error Arguments::pushArg(uint64_t arg) { + if (auto err = checkPushTooManyArgs()) { + return err; + } + + auto pos = currentPos++; + CircuitGate input = keySet.inputGate(pos); + if (input.shape.size != 0) { + return StreamStringError("argument #") << pos << " is not a scalar"; + } + if (!input.encryption.hasValue()) { + // clear scalar: just push the argument + if (input.shape.width != 64) { + return StreamStringError( + "scalar argument of with != 64 is not supported for DynamicLambda"); + } + preparedArgs.push_back((void *)arg); + return llvm::Error::success(); + } + // encrypted scalar: allocate, encrypt and push + LweCiphertext_u64 *ctArg; + if (auto err = keySet.allocate_lwe(pos, &ctArg)) { + return err; + } + allocatedCiphertexts.push_back(ctArg); + if (auto err = keySet.encrypt_lwe(pos, ctArg, arg)) { + return err; + } + preparedArgs.push_back((void *)ctArg); + return llvm::Error::success(); +} + +llvm::Error Arguments::pushArg(std::vector arg) { + return pushArg(8, (void *)arg.data(), {(int64_t)arg.size()}); +} + +llvm::Error Arguments::pushArg(size_t width, void *data, + llvm::ArrayRef shape) { + if (auto err = checkPushTooManyArgs()) { + return err; + } + auto pos = currentPos; + currentPos = currentPos + 1; + CircuitGate input = keySet.inputGate(pos); + // Check the width of data + if (input.shape.width > 64) { + return StreamStringError("argument #") + << pos << " width > 64 bits is not supported"; + } + auto roundedSize = bitWidthAsWord(input.shape.width); + if (width != roundedSize) { + return StreamStringError("argument #") + << pos << "width mismatch, got " << width << " expected " + << roundedSize; + } + // Check the shape of tensor + if (input.shape.dimensions.empty()) { + return StreamStringError("argument #") << pos << "is not a tensor"; + } + if (shape.size() != input.shape.dimensions.size()) { + return StreamStringError("argument #") + << pos << "has not the expected number of dimension, got " + << shape.size() << " expected " << input.shape.dimensions.size(); + } + for (size_t i = 0; i < shape.size(); i++) { + if (shape[i] != input.shape.dimensions[i]) { + return StreamStringError("argument #") + << pos << " has not the expected dimension #" << i << " , got " + << shape[i] << " expected " << input.shape.dimensions[i]; + } + } + if (input.encryption.hasValue()) { + // Encrypted tensor: for now we support only 8 bits for encrypted tensor + if (width != 8) { + return StreamStringError("argument #") + << pos << " width mismatch, expected 8 got " << width; + } + const uint8_t *data8 = (const uint8_t *)data; + + // Allocate a buffer for ciphertexts of size of tensor + auto ctBuffer = (LweCiphertext_u64 **)malloc(input.shape.size * + sizeof(LweCiphertext_u64 *)); + ciphertextBuffers.push_back(ctBuffer); + // Allocate ciphertexts and encrypt, for every values in tensor + for (size_t i = 0; i < input.shape.size; i++) { + if (auto err = this->keySet.allocate_lwe(pos, &ctBuffer[i])) { + return err; + } + allocatedCiphertexts.push_back(ctBuffer[i]); + if (auto err = this->keySet.encrypt_lwe(pos, ctBuffer[i], data8[i])) { + return err; + } + } + // Replace the data by the buffer to ciphertext + data = (void *)ctBuffer; + } + // allocated + preparedArgs.push_back(nullptr); + // aligned + preparedArgs.push_back(data); + // offset + preparedArgs.push_back((void *)0); + // sizes + for (size_t i = 0; i < shape.size(); i++) { + preparedArgs.push_back((void *)shape[i]); + } + // strides - FIXME make it works + // strides is an array of size equals to numDim + for (size_t i = 0; i < shape.size(); i++) { + preparedArgs.push_back((void *)0); + } + return llvm::Error::success(); +} + +llvm::Error Arguments::pushContext() { + if (currentPos < keySet.numInputs()) { + return StreamStringError("Missing arguments"); + } + preparedArgs.push_back(&context); + return llvm::Error::success(); +} + +llvm::Error Arguments::checkPushTooManyArgs() { + size_t arity = keySet.numInputs(); + if (currentPos < arity) { + return llvm::Error::success(); + } + return StreamStringError("function has arity ") + << arity << " but is applied to too many arguments"; +} + +} // namespace concretelang +} // namespace mlir \ No newline at end of file diff --git a/compiler/lib/TestLib/CMakeLists.txt b/compiler/lib/TestLib/CMakeLists.txt new file mode 100644 index 000000000..895602e77 --- /dev/null +++ b/compiler/lib/TestLib/CMakeLists.txt @@ -0,0 +1,16 @@ +add_mlir_library(ConcretelangTestLib + Arguments.cpp + DynamicLambda.cpp + DynamicModule.cpp + + ADDITIONAL_HEADER_DIRS + ${PROJECT_SOURCE_DIR}/include/concretelang/TestLib + + DEPENDS + MLIRConversionPassIncGen + + LINK_LIBS PUBLIC + + ConcretelangSupport + ConcretelangClientLib +) diff --git a/compiler/lib/TestLib/DynamicLambda.cpp b/compiler/lib/TestLib/DynamicLambda.cpp new file mode 100644 index 000000000..93754d942 --- /dev/null +++ b/compiler/lib/TestLib/DynamicLambda.cpp @@ -0,0 +1,224 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#include + +#include "concretelang/Support/CompilerEngine.h" +#include "concretelang/Support/Error.h" +#include "concretelang/TestLib/DynamicLambda.h" +#include "concretelang/TestLib/dynamicArityCall.h" + +namespace mlir { +namespace concretelang { + +template struct MemRefDescriptor { + LweCiphertext_u64 **allocated; + LweCiphertext_u64 **aligned; + size_t offset; + size_t sizes[N]; + size_t strides[N]; +}; + +llvm::Expected> decryptSlice(LweCiphertext_u64 **aligned, + KeySet &keySet, size_t start, + size_t size, + size_t stride = 1) { + stride = (stride == 0) ? 1 : stride; + std::vector result(size); + for (size_t i = 0; i < size; i++) { + size_t offset = start + i * stride; + auto err = keySet.decrypt_lwe(0, aligned[offset], result[i]); + if (err) { + return StreamStringError() + << "cannot decrypt result #" << i << ", err:" << err; + } + } + return result; +} + +llvm::Expected +DynamicLambda::load(std::string funcName, std::string outputLib) { + auto moduleOrErr = mlir::concretelang::DynamicModule::open(outputLib); + if (!moduleOrErr) { + return moduleOrErr.takeError(); + } + return mlir::concretelang::DynamicLambda::load(*moduleOrErr, funcName); +} + +llvm::Expected +DynamicLambda::load(std::shared_ptr module, + std::string funcName) { + DynamicLambda lambda; + lambda.module = + module; // prevent module and library handler from being destroyed + lambda.func = + (void *(*)(void *, ...))dlsym(module->libraryHandle, funcName.c_str()); + + if (auto err = dlerror()) { + return StreamStringError("Cannot open lambda: ") << err; + } + + auto param = + llvm::find_if(module->clientParametersList, [&](ClientParameters param) { + return param.functionName == funcName; + }); + + if (param == module->clientParametersList.end()) { + return StreamStringError("cannot find function ") + << funcName << "in client parameters"; + } + + if (param->outputs.size() != 1) { + return StreamStringError("DynamicLambda: output arity (") + << std::to_string(param->outputs.size()) + << ") != 1 is not supported"; + } + + if (!param->outputs[0].encryption.hasValue()) { + return StreamStringError( + "DynamicLambda: clear output is not yet supported"); + } + + lambda.clientParameters = *param; + return lambda; +} + +template <> +llvm::Expected invoke(DynamicLambda &lambda, + const Arguments &args) { + auto output = lambda.clientParameters.outputs[0]; + if (output.shape.size != 0) { + return StreamStringError("the function doesn't return a scalar"); + } + // Scalar encrypted result + auto fCasted = (LweCiphertext_u64 * (*)(void *...))(lambda.func); + ; + LweCiphertext_u64 *lweResult = + mlir::concretelang::call(fCasted, args.preparedArgs); + + uint64_t decryptedResult; + if (auto err = lambda.keySet->decrypt_lwe(0, lweResult, decryptedResult)) { + return std::move(err); + } + return decryptedResult; +} + +template +llvm::Expected> +DynamicLambda::invokeMemRefDecriptor(const Arguments &args) { + auto output = clientParameters.outputs[0]; + if (output.shape.size == 0) { + return StreamStringError("the function doesn't return a tensor"); + } + if (output.shape.dimensions.size() != Rank) { + return StreamStringError("the function doesn't return a tensor of rank ") + << Rank; + } + // Tensor encrypted result + auto fCasted = (MemRefDescriptor(*)(void *...))(func); + auto encryptedResult = mlir::concretelang::call(fCasted, args.preparedArgs); + + for (size_t dim = 0; dim < Rank; dim++) { + size_t actual_size = encryptedResult.sizes[dim]; + size_t expected_size = output.shape.dimensions[dim]; + if (actual_size != expected_size) { + return StreamStringError("the function returned a vector of size ") + << actual_size << " instead of size " << expected_size; + } + } + return encryptedResult; +} + +template <> +llvm::Expected> +invoke>(DynamicLambda &lambda, const Arguments &args) { + auto encryptedResultOrErr = lambda.invokeMemRefDecriptor<1>(args); + if (!encryptedResultOrErr) { + return encryptedResultOrErr.takeError(); + } + auto &encryptedResult = encryptedResultOrErr.get(); + auto &keySet = lambda.keySet; + return decryptSlice(encryptedResult.aligned, *keySet, encryptedResult.offset, + encryptedResult.sizes[0], encryptedResult.strides[0]); +} + +template <> +llvm::Expected>> +invoke>>(DynamicLambda &lambda, + const Arguments &args) { + auto encryptedResultOrErr = lambda.invokeMemRefDecriptor<2>(args); + if (!encryptedResultOrErr) { + return encryptedResultOrErr.takeError(); + } + auto &encryptedResult = encryptedResultOrErr.get(); + auto &keySet = lambda.keySet; + + std::vector> result; + result.reserve(encryptedResult.sizes[0]); + for (size_t i = 0; i < encryptedResult.sizes[0]; i++) { + // TODO : strides + int offset = encryptedResult.offset + i * encryptedResult.sizes[1]; + auto slice = + decryptSlice(encryptedResult.aligned, *keySet, offset, + encryptedResult.sizes[1], encryptedResult.strides[1]); + if (!slice) { + return StreamStringError(llvm::toString(slice.takeError())); + } + result.push_back(slice.get()); + } + return result; +} + +template <> +llvm::Expected>>> +invoke>>>(DynamicLambda &lambda, + const Arguments &args) { + auto encryptedResultOrErr = lambda.invokeMemRefDecriptor<3>(args); + if (!encryptedResultOrErr) { + return encryptedResultOrErr.takeError(); + } + auto &encryptedResult = encryptedResultOrErr.get(); + auto &keySet = lambda.keySet; + + std::vector>> result0; + result0.reserve(encryptedResult.sizes[0]); + for (size_t i = 0; i < encryptedResult.sizes[0]; i++) { + std::vector> result1; + result1.reserve(encryptedResult.sizes[1]); + for (size_t j = 0; j < encryptedResult.sizes[1]; j++) { + // TODO : strides + int offset = encryptedResult.offset + + i * encryptedResult.sizes[1] * encryptedResult.sizes[2] + + j * encryptedResult.sizes[2]; + auto slice = + decryptSlice(encryptedResult.aligned, *keySet, offset, + encryptedResult.sizes[2], encryptedResult.strides[2]); + if (!slice) { + return StreamStringError(llvm::toString(slice.takeError())); + } + result1.push_back(slice.get()); + } + result0.push_back(result1); + } + return result0; +} + +llvm::Error DynamicLambda::generateKeySet(llvm::Optional cache, + uint64_t seed_msb, + uint64_t seed_lsb) { + auto maybeKeySet = + cache.hasValue() + ? cache->tryLoadOrGenerateSave(clientParameters, seed_msb, seed_lsb) + : KeySet::generate(clientParameters, seed_msb, seed_lsb); + + if (auto err = maybeKeySet.takeError()) { + return err; + } + keySet = std::move(maybeKeySet.get()); + return llvm::Error::success(); +} + +} // namespace concretelang +} // namespace mlir \ No newline at end of file diff --git a/compiler/lib/TestLib/DynamicModule.cpp b/compiler/lib/TestLib/DynamicModule.cpp new file mode 100644 index 000000000..d319a4ea7 --- /dev/null +++ b/compiler/lib/TestLib/DynamicModule.cpp @@ -0,0 +1,61 @@ +// Part of the Concrete Compiler Project, under the BSD3 License with Zama +// Exceptions. See +// https://github.com/zama-ai/homomorphizer/blob/master/LICENSE.txt for license +// information. + +#include +#include + +#include "concretelang/Support/CompilerEngine.h" +#include "concretelang/Support/Error.h" + +#include "concretelang/TestLib/DynamicModule.h" + +namespace mlir { +namespace concretelang { + +DynamicModule::~DynamicModule() { + if (libraryHandle != nullptr) { + dlclose(libraryHandle); + } +} + +llvm::Expected> +DynamicModule::open(std::string path) { + std::shared_ptr module = std::make_shared(); + if (auto err = module->loadClientParametersJSON(path)) { + return StreamStringError("Cannot load client parameters: ") + << llvm::toString(std::move(err)); + } + if (auto err = module->loadSharedLibrary(path)) { + return StreamStringError("Cannot load client parameters: ") + << llvm::toString(std::move(err)); + } + return module; +} + +llvm::Error DynamicModule::loadSharedLibrary(std::string path) { + libraryHandle = dlopen( + CompilerEngine::Library::getSharedLibraryPath(path).c_str(), RTLD_LAZY); + if (!libraryHandle) { + return StreamStringError("Cannot open shared library") << dlerror(); + } + return llvm::Error::success(); +} + +llvm::Error DynamicModule::loadClientParametersJSON(std::string path) { + + std::ifstream file(CompilerEngine::Library::getClientParametersPath(path)); + std::string content((std::istreambuf_iterator(file)), + (std::istreambuf_iterator())); + llvm::Expected> expectedClientParams = + llvm::json::parse>(content); + if (auto err = expectedClientParams.takeError()) { + return StreamStringError("Cannot open client parameters: ") << err; + } + this->clientParametersList = *expectedClientParams; + return llvm::Error::success(); +} + +} // namespace concretelang +} // namespace mlir diff --git a/compiler/src/CMakeLists.txt b/compiler/src/CMakeLists.txt index 53a785091..0944d9899 100644 --- a/compiler/src/CMakeLists.txt +++ b/compiler/src/CMakeLists.txt @@ -22,6 +22,7 @@ if(CONCRETELANG_PARALLEL_EXECUTION_ENABLED) RTDialect ConcretelangSupport + ConcretelangTestLib -Wl,-rpath,${CMAKE_BINARY_DIR}/lib/Runtime -Wl,-rpath,${HPX_DIR}/../../ diff --git a/compiler/tests/CMakeLists.txt b/compiler/tests/CMakeLists.txt index 9b726791c..214fe2fd9 100644 --- a/compiler/tests/CMakeLists.txt +++ b/compiler/tests/CMakeLists.txt @@ -1,4 +1,5 @@ if (CONCRETELANG_UNIT_TESTS) add_subdirectory(unittest) add_subdirectory(Support) + add_subdirectory(TestLib) endif() diff --git a/compiler/tests/TestLib/CMakeLists.txt b/compiler/tests/TestLib/CMakeLists.txt new file mode 100644 index 000000000..25a1763c9 --- /dev/null +++ b/compiler/tests/TestLib/CMakeLists.txt @@ -0,0 +1,24 @@ +enable_testing() + +include_directories(${PROJECT_SOURCE_DIR}/include) + +add_executable( + testlib_unit_test + testlib_unit_test.cpp +) + +set_source_files_properties( + testlib_unit_test.cpp + + PROPERTIES COMPILE_FLAGS "-fno-rtti" +) + +target_link_libraries( + testlib_unit_test + gtest_main + ConcretelangRuntime + ConcretelangTestLib +) + +include(GoogleTest) +gtest_discover_tests(testlib_unit_test) diff --git a/compiler/tests/TestLib/out/.keep b/compiler/tests/TestLib/out/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/compiler/tests/TestLib/testlib_unit_test.cpp b/compiler/tests/TestLib/testlib_unit_test.cpp new file mode 100644 index 000000000..af6208d7a --- /dev/null +++ b/compiler/tests/TestLib/testlib_unit_test.cpp @@ -0,0 +1,241 @@ +#include + +#include +#include + +#include "../unittest/end_to_end_jit_test.h" +#include "concretelang/TestLib/DynamicLambda.h" + +const std::string FUNCNAME = "main"; + +template +using TypedDynamicLambda = mlir::concretelang::TypedDynamicLambda; + +using scalar = uint64_t; +using tensor1_in = std::vector; +using tensor1_out = std::vector; +using tensor2_out = std::vector>; +using tensor3_out = std::vector>>; + +std::vector +values_7bits() { + return {0, 1, 2, 63, 64, 65, 125, 126}; +} + +llvm::Expected +compile(std::string outputLib, std::string source) { + std::vector sources = {source}; + std::shared_ptr ccx = + mlir::concretelang::CompilationContext::createShared(); + mlir::concretelang::JitCompilerEngine ce {ccx}; + ce.setClientParametersFuncName(FUNCNAME); + return ce.compile(sources, outputLib); +} + +template +std::string outputLibFromThis(Info *info) { + return "tests/TestLib/out/" + std::string(info->name()); +} + +TEST(CompiledModule, call_1s_1s) { + std::string source = R"( +func @main(%arg0: !FHE.eint<7>) -> !FHE.eint<7> { + return %arg0: !FHE.eint<7> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + for(auto a: values_7bits()) { + auto res = lambda->call(a); + ASSERT_EXPECTED_VALUE(res, a); + } +} + +TEST(CompiledModule, call_2s_1s) { + std::string source = R"( +func @main(%arg0: !FHE.eint<7>, %arg1: !FHE.eint<7>) -> !FHE.eint<7> { + %1 = "FHE.add_eint"(%arg0, %arg1): (!FHE.eint<7>, !FHE.eint<7>) -> (!FHE.eint<7>) + return %1: !FHE.eint<7> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + for(auto a: values_7bits()) for(auto b: values_7bits()) { + auto res = lambda->call(a, b); + ASSERT_EXPECTED_VALUE(res, a + b); + } +} + +TEST(CompiledModule, call_1s_1t) { + std::string source = R"( +func @main(%arg0: !FHE.eint<7>) -> tensor<1x!FHE.eint<7>> { + %1 = tensor.from_elements %arg0 : tensor<1x!FHE.eint<7>> + return %1: tensor<1x!FHE.eint<7>> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + for(auto a: values_7bits()) { + auto res = lambda->call(a); + ASSERT_EXPECTED_SUCCESS(res); + tensor1_out v = res.get(); + EXPECT_EQ(v[0], a); + } +} + +TEST(CompiledModule, call_2s_1t) { + std::string source = R"( +func @main(%arg0: !FHE.eint<7>, %arg1: !FHE.eint<7>) -> tensor<2x!FHE.eint<7>> { + %1 = tensor.from_elements %arg0, %arg1 : tensor<2x!FHE.eint<7>> + return %1: tensor<2x!FHE.eint<7>> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + for(auto a : values_7bits()) { + auto res = lambda->call(a, a+1); + ASSERT_EXPECTED_SUCCESS(res); + tensor1_out v = res.get(); + EXPECT_EQ((scalar)v[0], a); + EXPECT_EQ((scalar)v[1], a + 1u); + } +} + +TEST(CompiledModule, call_1t_1s) { + std::string source = R"( +func @main(%arg0: tensor<1x!FHE.eint<7>>) -> !FHE.eint<7> { + %c0 = arith.constant 0 : index + %1 = tensor.extract %arg0[%c0] : tensor<1x!FHE.eint<7>> + return %1: !FHE.eint<7> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + for(uint8_t a : values_7bits()) { + tensor1_in ta = {a}; + auto res = lambda->call(ta); + ASSERT_EXPECTED_VALUE(res, a); + } +} + +TEST(CompiledModule, call_1t_1t) { + std::string source = R"( +func @main(%arg0: tensor<3x!FHE.eint<7>>) -> tensor<3x!FHE.eint<7>> { + return %arg0: tensor<3x!FHE.eint<7>> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + tensor1_in ta = {1, 2, 3}; + auto res = lambda->call(ta); + ASSERT_EXPECTED_SUCCESS(res); + tensor1_out v = res.get(); + for(size_t i = 0; i < v.size(); i++) { + EXPECT_EQ(v[i], ta[i]); + } +} + +TEST(CompiledModule, call_2t_1s) { + std::string source = R"( +func @main(%arg0: tensor<3x!FHE.eint<7>>, %arg1: tensor<3x!FHE.eint<7>>) -> !FHE.eint<7> { + %1 = "FHELinalg.add_eint"(%arg0, %arg1) : (tensor<3x!FHE.eint<7>>, tensor<3x!FHE.eint<7>>) -> tensor<3x!FHE.eint<7>> + %c1 = arith.constant 1 : i8 + %2 = tensor.from_elements %c1, %c1, %c1 : tensor<3xi8> + %3 = "FHELinalg.dot_eint_int"(%1, %2) : (tensor<3x!FHE.eint<7>>, tensor<3xi8>) -> !FHE.eint<7> + return %3: !FHE.eint<7> +} +)"; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda>::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + tensor1_in ta {1, 2, 3}; + std::array tb {5, 7, 9}; + auto res = lambda->call(ta, tb); + auto expected = std::accumulate(ta.begin(), ta.end(), 0u) + + std::accumulate(tb.begin(), tb.end(), 0u); + ASSERT_EXPECTED_VALUE(res, expected); +} + +TEST(CompiledModule, call_1tr2_1tr2) { + std::string source = R"( +func @main(%arg0: tensor<2x3x!FHE.eint<7>>) -> tensor<2x3x!FHE.eint<7>> { + return %arg0: tensor<2x3x!FHE.eint<7>> +} +)"; + using tensor2_in = std::array, 2>; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + tensor2_in ta = {{ + {1, 2, 3}, + {4, 5, 6} + }}; + auto res = lambda->call(ta); + ASSERT_EXPECTED_SUCCESS(res); + tensor2_out v = res.get(); + for(size_t i = 0; i < v.size(); i++) { + for(size_t j = 0; j < v.size(); j++) { + EXPECT_EQ(v[i][j], ta[i][j]); + } + } +} + + +TEST(CompiledModule, call_1tr3_1tr3) { + std::string source = R"( +func @main(%arg0: tensor<2x3x1x!FHE.eint<7>>) -> tensor<2x3x1x!FHE.eint<7>> { + return %arg0: tensor<2x3x1x!FHE.eint<7>> +} +)"; + using tensor3_in = std::array, 3>, 2>; + std::string outputLib = outputLibFromThis(this->test_info_); + auto compiled = compile(outputLib, source); + ASSERT_EXPECTED_SUCCESS(compiled); + auto lambda = TypedDynamicLambda::load(FUNCNAME, outputLib); + ASSERT_EXPECTED_SUCCESS(lambda); + ASSERT_LLVM_ERROR(lambda->generateKeySet(getTestKeySetCache())); + tensor3_in ta = {{ + {{ {1}, {2}, {3} }}, + {{ {4}, {5}, {6} }} + }}; + auto res = lambda->call(ta); + ASSERT_EXPECTED_SUCCESS(res); + tensor3_out v = res.get(); + for(size_t i = 0; i < v.size(); i++) { + for(size_t j = 0; j < v[i].size(); j++) { + for(size_t k = 0; k < v[i][j].size(); k++) { + EXPECT_EQ(v[i][j][k], ta[i][j][k]); + } + } + } +} diff --git a/compiler/tests/unittest/end_to_end_jit_test.h b/compiler/tests/unittest/end_to_end_jit_test.h index a6e377b06..f1d825b50 100644 --- a/compiler/tests/unittest/end_to_end_jit_test.h +++ b/compiler/tests/unittest/end_to_end_jit_test.h @@ -93,6 +93,17 @@ static bool assert_expected_value(llvm::Expected &&val, const V &exp) { } \ } while (0) +static inline llvm::Optional getTestKeySetCache() { + + llvm::SmallString<0> cachePath; + llvm::sys::path::system_temp_directory(true, cachePath); + llvm::sys::path::append(cachePath, "KeySetCache"); + + auto cachePathStr = std::string(cachePath); + return llvm::Optional( + mlir::concretelang::KeySetCache(cachePathStr)); +} + // Jit-compiles the function specified by `func` from `src` and // returns the corresponding lambda. Any compilation errors are caught // and reult in abnormal termination. @@ -103,16 +114,6 @@ internalCheckedJit(F checkFunc, llvm::StringRef src, bool useDefaultFHEConstraints = false, bool autoParallelize = false) { - llvm::SmallString<0> cachePath; - - llvm::sys::path::system_temp_directory(true, cachePath); - - llvm::sys::path::append(cachePath, "KeySetCache"); - - auto cachePathStr = std::string(cachePath); - auto optCache = llvm::Optional( - mlir::concretelang::KeySetCache(cachePathStr)); - mlir::concretelang::JitCompilerEngine engine; if (useDefaultFHEConstraints) @@ -124,7 +125,7 @@ internalCheckedJit(F checkFunc, llvm::StringRef src, #endif llvm::Expected lambdaOrErr = - engine.buildLambda(src, func, optCache); + engine.buildLambda(src, func, getTestKeySetCache()); if (!lambdaOrErr) { std::cout << llvm::toString(lambdaOrErr.takeError()) << std::endl;