delorie.com/archives/browse.cgi | search |
X-Recipient: | archive-cygwin AT delorie DOT com |
DomainKey-Signature: | a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id |
:list-unsubscribe:list-subscribe:list-archive:list-post | |
:list-help:sender:mime-version:in-reply-to:references:from:date | |
:message-id:subject:to:content-type:content-transfer-encoding; | |
q=dns; s=default; b=B6+igNMDFRXbD2dQ0iZXG0jHeHuuKoc8A0NdyzylQb2 | |
kRW9iyjRdHN9QcqdHZSdea1qIkRloS38yaBVyn4RACXJOAQ9tzFFs8E+8rib82ak | |
nxZZ7RibiIH3RSIcUUGZkOBRtT37fKRhy21+HfawKIbRceKEqvJvAgKyQtcULX/4 | |
= | |
DKIM-Signature: | v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id |
:list-unsubscribe:list-subscribe:list-archive:list-post | |
:list-help:sender:mime-version:in-reply-to:references:from:date | |
:message-id:subject:to:content-type:content-transfer-encoding; | |
s=default; bh=bTeCFOkUWKQSWEBXFBRet15Y9+g=; b=wrDfJDHxP2Z4rqhhy | |
gXtHSp1sdfNxsx0E96i/5C+/uo1UFxsdmTCq755e1wBDWK3dZKLhsxxKjDIpu5IG | |
Cr529WvFU5cW1fVrqP7tp4D/au/hZ/5KrOTGHV8R7T8Cdpt1RferGLtD5m1Qjj08 | |
afasSG+MZmlVwDRz8HBK3be9s4= | |
Mailing-List: | contact cygwin-help AT cygwin DOT com; run by ezmlm |
List-Id: | <cygwin.cygwin.com> |
List-Subscribe: | <mailto:cygwin-subscribe AT cygwin DOT com> |
List-Archive: | <http://sourceware.org/ml/cygwin/> |
List-Post: | <mailto:cygwin AT cygwin DOT com> |
List-Help: | <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs> |
Sender: | cygwin-owner AT cygwin DOT com |
Mail-Followup-To: | cygwin AT cygwin DOT com |
Delivered-To: | mailing list cygwin AT cygwin DOT com |
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 DOT m DOT bray AT gmail DOT com, U*erik.m.bray |
X-HELO: | mail-yb0-f174.google.com |
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 |
In-Reply-To: | <CAOTD34Y=0udiWCAmkyEywJA6=NrUkG-T9hqXNHWckMbgkdmn_w@mail.gmail.com> |
References: | <6f28f46906804c6f8f6b4b861e202492 AT CASMBX02 DOT oslo DOT ngi DOT no> <d252aaae-b298-6fc8-7e5b-8d8be9f27f21 AT redhat DOT com> <CAOTD34Y=0udiWCAmkyEywJA6=NrUkG-T9hqXNHWckMbgkdmn_w AT mail DOT gmail DOT com> |
From: | Erik Bray <erik DOT m DOT bray AT gmail DOT com> |
Date: | Wed, 24 May 2017 18:53:04 +0200 |
Message-ID: | <CAOTD34YW5KoSH3unhrHfEW7Ni8-DGOPsiXNTwn75UwOhdUfVbg@mail.gmail.com> |
Subject: | Re: bug in lrint [was: FW: Printing long int in C program under cygwin64] |
To: | cygwin AT cygwin DOT com |
X-IsSubscribed: | yes |
X-MIME-Autoconverted: | from quoted-printable to 8bit by delorie.com id v4OGrN3T010667 |
On Wed, May 24, 2017 at 5:55 PM, Erik Bray <erik DOT m DOT bray AT gmail DOT com> 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 installed on a Windows 10 machine. >>> >>> Below is a test program followed by its output to demonstrate the problem. 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 treated as an unsigned integer. >>> Any help or hints would be much appreciated. >>> >>> Regards >>> Carl Fredrik >>> >>> #include <stdio.h> /* printf */ >>> #include <math.h> /* lrint */ >>> >>> int main () >>> { >>> char text[64]; >>> printf ( "int -2 = %i\n", -2 ); >>> printf ( "int -1 = %i\n", -1 ); >>> printf ( "int 0 = %i\n", 0 ); >>> printf ( "int 1 = %i\n", 1 ); >> >> Okay so far. >> >>> printf ( "long int -2 = %li\n", -2 ); >>> printf ( "long int -1 = %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 = %li\n", (long int)-1 ); >>> printf ( "type cast lrint(-1.0) = %li\n", (long int)lrint(-1.0) ); >>> printf ( "lrint(-1.0) = %li\n", lrint(-1.0) ); >>> printf ( "lrint(1.0) = %li\n", lrint(1.0) ); >> >> Okay. >> >>> printf ( "long int 0 = %li\n", 0 ); >>> printf ( "long int 1 = %li\n", 1 ); >>> sprintf( text,"long int -1 = %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 = -2 >>> int -1 = -1 >>> int 0 = 0 >>> int 1 = 1 >>> long int -2 = 4294967294 >>> long int -1 = 4294967295 >> >> Evidence of your bugs. >> >>> type cast -1 = -1 >>> type cast lrint(-1.0) = 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 = 0L; >> #if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || >> defined(__i386__) >> __asm__ __volatile__ ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); >> #elif defined(__arm__) || defined(_ARM_) >> retval = __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 <lrint>: > 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
webmaster | delorie software privacy |
Copyright © 2019 by DJ Delorie | Updated Jul 2019 |