X-Recipient: archive-cygwin@delorie.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=fLkE57M5WwHESx20+yE4dVwEg0j/NSK1BfRUirEHf9Q
	BDRiV3W/b3UmvpxnoLYXkKNRxkBHMRtzaEL7U1ctJXIu1gJK37ym2jyOdBsh91yg
	8NruwfWQPOz/3mwC0X3b9nMHCzK69ccI9ExPHqwmOn5vGDbSX/ulC4Wz5frdwg18
	=
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=bVk1vx9vkq1qzCyF8LmFq0+wA8Y=; b=MxmVF5IdVlpe6pt7s
	PStb5Us9EB7DoCoV1It9pmNHwB+mgUvTvjFJDwDF78EWQX4RHlZeckILjgleWXQT
	j9vaKbYhB7ubqA3x6W39qMMml/WGU4qjlbholB/r/g8TIs+cAdcRBNXeywiBYhfQ
	aDgRpeV6kQOYbc21Z+nSk9I+Sk=
Mailing-List: contact cygwin-help@cygwin.com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe@cygwin.com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin@cygwin.com>
List-Help: <mailto:cygwin-help@cygwin.com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner@cygwin.com
Mail-Followup-To: cygwin@cygwin.com
Delivered-To: mailing list cygwin@cygwin.com
Authentication-Results: sourceware.org; auth=none
X-Virus-Found: No
X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=no version=3.3.2 spammy=
X-HELO: mail-yw0-f180.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=gf6lTuzn/gvRA4NybthapStojgNnM+U+I0KMI6kDJDc=;        b=Rk+fgMyseJAglAgGGb18r6cv/lereQHIQVb+K9KCUKnMRwRPqO0E9IX8g0Nmd0epNT         wwWrwPrhrMLhvS39f4fBbZs40fxqVvzu3A+qbQQD2hpckylQVbrlCe8FdtT3aI5je3y6         QOuncFrCTmeAYzzTA/r3l/AYD8pZFmrRmHs7poRaMqs4OOTeA9Zjfh2aCwvCSFXMpozf         gX8HobOD7L9K302Plh/0KY/v1qOOJittwqsGkA2ul3y12Wt6hBjyos5FhvY7g5bFBaxh         o6e8CMq6pXNt+wqfLkX4boyBMCTpG80JXgnHFCOu6d0vqn6FMPixzqgaxKKdZD/iGlgw         fKcQ==
X-Gm-Message-State: AODbwcCoDNjg4Rx55MZmHdUCDTLQ/+VVPBmBzL/ZgWO00EaLjHQM3v5G	2Q+uRj4yJeAwJdX+52RavImVf33YsYBdOFo=
X-Received: by 10.13.233.3 with SMTP id s3mr28892846ywe.242.1495641353186; Wed, 24 May 2017 08:55:53 -0700 (PDT)
MIME-Version: 1.0
In-Reply-To: <d252aaae-b298-6fc8-7e5b-8d8be9f27f21@redhat.com>
References: <6f28f46906804c6f8f6b4b861e202492@CASMBX02.oslo.ngi.no> <d252aaae-b298-6fc8-7e5b-8d8be9f27f21@redhat.com>
From: Erik Bray <erik.m.bray@gmail.com>
Date: Wed, 24 May 2017 17:55:52 +0200
Message-ID: <CAOTD34Y=0udiWCAmkyEywJA6=NrUkG-T9hqXNHWckMbgkdmn_w@mail.gmail.com>
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"
X-IsSubscribed: yes
Content-Transfer-Encoding: 8bit
X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id v4OFuElw004729

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.

Best,
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


