From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 47589 invoked by alias); 10 Oct 2016 07:04:07 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 47575 invoked by uid 89); 10 Oct 2016 07:04:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.4 required=5.0 tests=BAYES_00,RCVD_IN_PBL,RDNS_DYNAMIC,SPF_HELO_PASS,SPF_PASS autolearn=no version=3.3.2 spammy=HTo:U*libffi-discuss, H*Ad:U*libffi-discuss, i1, cif X-HELO: dtbo.net Received: from mic92-4-82-224-21-170.fbx.proxad.net (HELO dtbo.net) (82.224.21.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Oct 2016 07:03:55 +0000 Received: by dtbo.net (Postfix, from userid 1000) id 7C5A422200C; Mon, 10 Oct 2016 09:03:52 +0200 (CEST) Date: Mon, 10 Oct 2016 07:04:00 -0000 From: Damien =?iso-8859-1?Q?Th=E9bault?= To: libffi-discuss@sourceware.org Subject: Floating-point variadic function call Message-ID: <20161010070352.GA11072@han> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="YiEDa0DAkWCtVeE4" Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-IsSubscribed: yes X-SW-Source: 2016/txt/msg00042.txt.bz2 --YiEDa0DAkWCtVeE4 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1240 Hello, I am trying to use libffi to call various functions, and my first try was with printf(). As this is a variadic function, I used ffi_prep_cif_var(). Everything seems to be working, except with floats, which are not working, and are even generating wrong memory accesses (detected by valgrind). A similar function with ffi_prep_cif() and floats is working properly. Could type promotion from float to double be the issue here ? Does libffi handle type promotion in variadic calls or is it the caller's job ? I tested on a x86_64 computer both 64-bit and 32-bit versions (the latter compiled with -m32) as well as ARM under qemu. In all those cases, I didn't get the proper result with floats while doubles are ok, as well as chars. I've attached a sample source file that reproduces the problem and here is the output of one test run: $ gcc $(pkg-config --cflags --libs libffi) -std=c99 -pedantic -Wall -Wextra libffi_variadic_printf.c -o libffi_variadic_printf $ ./libffi_variadic_printf Non-variadic call: [1.100000,2.200000,3.300000,4.400000,5.500000,6.600000,7.700000,8.800000,9.900000] result is 83 Variadic call: [0.000000,0.000000,0.000000,0.000000,0.000000,91750.390826,0.000000,0.000000,0.000000] result is 87 Thanks, --YiEDa0DAkWCtVeE4 Content-Type: text/x-c; charset=us-ascii Content-Disposition: attachment; filename="libffi_variadic_printf.c" Content-length: 2018 #include #include int print9float(const char *fmt, float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9) { return printf(fmt, f1, f2, f3, f4, f5, f6, f7, f8, f9); } void test_float() { size_t i; ffi_cif cif; ffi_type *arg_types[10]; void *arg_values[10]; char *fmt = "[%f,%f,%f,%f,%f,%f,%f,%f,%f]\n"; float floatargs[9] = {1.1f,2.2f,3.3f,4.4f,5.5f,6.6f,7.7f,8.8f,9.9f}; ffi_status status; int result; arg_types[0] = &ffi_type_pointer; for(i=1 ; i<10 ; i++) { arg_types[i] = &ffi_type_float; } if((status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 10, &ffi_type_sint, arg_types)) != FFI_OK) { fprintf(stderr, "ffi_prep_cif_var() failed!\n"); return; } arg_values[0] = &fmt; for(i=1 ; i<10 ; i++) { arg_values[i] = &floatargs[i-1]; } printf("Non-variadic call:\n"); ffi_call(&cif, FFI_FN(print9float), &result, arg_values); printf("result is %i\n", result); } void test_varfloat() { size_t i; ffi_cif cif; ffi_type *arg_types[10]; void *arg_values[10]; char *fmt = "[%f,%f,%f,%f,%f,%f,%f,%f,%f]\n"; float floatargs[9] = {1.1f,2.2f,3.3f,4.4f,5.5f,6.6f,7.7f,8.8f,9.9f}; ffi_status status; int result; arg_types[0] = &ffi_type_pointer; for(i=1 ; i<10 ; i++) { arg_types[i] = &ffi_type_float; } if((status = ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 10, &ffi_type_sint, arg_types)) != FFI_OK) { fprintf(stderr, "ffi_prep_cif_var() failed!\n"); return; } arg_values[0] = &fmt; for(i=1 ; i<10 ; i++) { arg_values[i] = &floatargs[i-1]; } printf("Variadic call:\n"); ffi_call(&cif, FFI_FN(printf), &result, arg_values); printf("result is %i\n", result); } int main() { test_float(); test_varfloat(); return 0; } --YiEDa0DAkWCtVeE4--