From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11433 invoked by alias); 24 May 2017 16:53:07 -0000 Mailing-List: contact cygwin-help@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner@cygwin.com Mail-Followup-To: cygwin@cygwin.com Received: (qmail 11393 invoked by uid 89); 24 May 2017 16:53:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=bray, Bray, erik.m.bray@gmail.com, U*erik.m.bray X-HELO: mail-yb0-f174.google.com Received: from mail-yb0-f174.google.com (HELO mail-yb0-f174.google.com) (209.85.213.174) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 24 May 2017 16:53:03 +0000 Received: by mail-yb0-f174.google.com with SMTP id 132so46922107ybq.1 for ; Wed, 24 May 2017 09:53:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:content-transfer-encoding; bh=7PsUpACblaapQfJr+iXbNxcaEkiqQj/5pAv5kQuwU8E=; b=a+kqerOF2spaV4Q7MI5gwTJVyQ6KzHIBMJV7umjO6WjnQnQQmlVDdMXUzg11mf5yXr 9GWJo0Ofo//+lL8WYcmNe/C/rlWnLCL7ei8cXHOKKEtfF5KdpOUpAN7xKcLo5AfL32HS Q6xDo0d9Az2FhdQjCyvFhYlOWw3Bkb8c12mMIvrgSOXnZ/8/8OHlptY+2137a7nZrJKP zLzMg7EtHKA2lu9/WSk+H2u9bLjwuwnAOPlvp6gWiEbgElQtKf6ne+DhQ9vUH1SC1XrD Z0tEth7gY/CQK79kW/0rTDL0VJQK96JVdNv8gULrmtA9+RtcPHs/1A6KB49z4oe992E5 pH1A== X-Gm-Message-State: AODbwcBMI34qGQtWtX9r8J9fhGLQUmdBq9l289GnPBCNypzsAK/D/KWS qn+6CeCLY1/IIj7aDSwFyNH0YvO5rdvG X-Received: by 10.37.65.199 with SMTP id o190mr29535141yba.142.1495644784956; Wed, 24 May 2017 09:53:04 -0700 (PDT) MIME-Version: 1.0 Received: by 10.37.164.34 with HTTP; Wed, 24 May 2017 09:53:04 -0700 (PDT) In-Reply-To: References: <6f28f46906804c6f8f6b4b861e202492@CASMBX02.oslo.ngi.no> From: Erik Bray Date: Wed, 24 May 2017 16:57:00 -0000 Message-ID: Subject: Re: bug in lrint [was: FW: Printing long int in C program under cygwin64] To: cygwin@cygwin.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2017-05/txt/msg00393.txt.bz2 On Wed, May 24, 2017 at 5:55 PM, Erik Bray wrote: > On Wed, May 24, 2017 at 2:33 PM, Eric Blake wrote: >> On 05/24/2017 07:00 AM, Carl Fredrik Forsberg wrote: >>> I am experiencing problems printing long int values under cygwin64 inst= alled on a Windows 10 machine. >>> >>> Below is a test program followed by its output to demonstrate the probl= em. The program was initially written to demonstrate the output from lrint(= ), and developed further to demonstrate to myself how negative integers are= tackled by printf type specifiers (e.g. %li, %ld etc). >> >> Are you compiling with -Wall, or even -Wformat? >> >>> >>> My understanding is that lrint() should return a long int. However I am= unable to get printf to print the correct number. Instead its output is tr= eated as an unsigned integer. >>> Any help or hints would be much appreciated. >>> >>> Regards >>> Carl Fredrik >>> >>> #include /* printf */ >>> #include /* lrint */ >>> >>> int main () >>> { >>> char text[64]; >>> printf ( "int -2 =3D %i\n", -2 ); >>> printf ( "int -1 =3D %i\n", -1 ); >>> printf ( "int 0 =3D %i\n", 0 ); >>> printf ( "int 1 =3D %i\n", 1 ); >> >> Okay so far. >> >>> printf ( "long int -2 =3D %li\n", -2 ); >>> printf ( "long int -1 =3D %li\n", -1 ); >> >> Both buggy. You are passing an int through varargs, but then telling >> printf to grab a long int. It may or may not work depending on ABI and >> stack sizes and what not, but gcc will warn you that it is bogus. >> >>> printf ( "type cast -1 =3D %li\n", (long int)-1 ); >>> printf ( "type cast lrint(-1.0) =3D %li\n", (long int)lrint(-1.0) ); >>> printf ( "lrint(-1.0) =3D %li\n", lrint(-1.0) ); >>> printf ( "lrint(1.0) =3D %li\n", lrint(1.0) ); >> >> Okay. >> >>> printf ( "long int 0 =3D %li\n", 0 ); >>> printf ( "long int 1 =3D %li\n", 1 ); >>> sprintf( text,"long int -1 =3D %li", -1 ); >> >> Buggy. >> >>> printf ( "Via sprintf: %s\n", text); >> >> Okay (well, if you overlook the fact that text was populated in a buggy >> manner) >> >>> printf ( "size of long int: %i\n", sizeof(long int)); >>> printf ( "size of int: %i\n", sizeof(int)); >> >> Buggy. size_t should be printed with %zi, not %i (since size_t and int >> are not necessarily the same type). >> >>> return 0; >>> } >>> >>> >>> compiled by: >>> gcc lrint_test.c -o lrint_test.exe >> >> Missing -Wall. Also, some platforms require the use of -lm to actually >> link with lrint() (cygwin does not, though). >> >>> >>> Output: >>> >>> int -2 =3D -2 >>> int -1 =3D -1 >>> int 0 =3D 0 >>> int 1 =3D 1 >>> long int -2 =3D 4294967294 >>> long int -1 =3D 4294967295 >> >> Evidence of your bugs. >> >>> type cast -1 =3D -1 >>> type cast lrint(-1.0) =3D 4294967295 >> >> Now that's an interesting one - it may be that cygwin1.dll actually has >> buggy behavior in lrint(). In the source code, cygwin/math/lrint.c is >> dropping down to assembly; it could very well be that the assembly code >> is incorrectly truncating things at 32 bits (where it is just fine for >> 32-bit Cygwin, but wrong for 64-bit): >> >> long lrint (double x) >> { >> long retval =3D 0L; >> #if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || >> defined(__i386__) >> __asm__ __volatile__ ("fistpl %0" : "=3Dm" (retval) : "t" (x) : "st"); >> #elif defined(__arm__) || defined(_ARM_) >> retval =3D __lrint_internal(x); >> #endif >> return retval; >> } >> >> But I'm not an assembly coding expert, so perhaps someone else will spot >> the fix faster. > > I took a look at this. The code in Cygwin looks fine, I think. But > the assembly is wrong: > > 000000018015cd40 : > 18015cd40: 48 83 ec 28 sub $0x28,%rsp > 18015cd44: f2 0f 11 44 24 08 movsd %xmm0,0x8(%rsp) > 18015cd4a: dd 44 24 08 fldl 0x8(%rsp) > 18015cd4e: db 5c 24 18 fistpl 0x18(%rsp) > 18015cd52: 48 8b 44 24 18 mov 0x18(%rsp),%rax > 18015cd57: 48 83 c4 28 add $0x28,%rsp > 18015cd5b: c3 retq > > That last `mov` should be a `movq`. The result in $rsp+0x18 is > correct (I checked in gdb), but the `mov` truncates it. Not sure if > that's a gcc bug or what. Actually, I take it back. gdb/objdump (and presumably binutils in general) was being deceptive to me about the nature of that mov instruction. And in fact the fistpl should be fistpq. That fixes it. Erik -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple