Package: tcc
Version: 0.9.26~git20120612.ad5f375-5
Severity: important
Tags: patch upstream
On i386 tcc can fails to read a long long value. A simple test case
showing the problem:
long long int ll[] = { 1LL, 2LL };
int main (void)
{
long long int lli;
lli = 1LL;
return ll[lli];
}
This program returns 0 instead of 2. This could cause programs compiled
with tcc on i386 to misbehave.
Best regards,
Thomas Preud'homme
-- System Information:
Debian Release: wheezy/sid
APT prefers unstable
APT policy: (990, 'unstable'), (500, 'stable-updates'), (500, 'testing'),
(500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 3.2.0-3-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages tcc depends on:
ii dpkg 1.16.7
ii install-info 4.13a.dfsg.1-10
ii libc6 2.13-34
Versions of packages tcc recommends:
ii libc6-dev [libc-dev] 2.13-34
tcc suggests no packages.
-- no debconf information
>From d1694f7d7e6d96f64d1330c9b43491b613272b1e Mon Sep 17 00:00:00 2001
From: Thomas Preud'homme <[email protected]>
Date: Wed, 11 Jul 2012 23:39:05 +0200
Subject: [PATCH] get_reg(): try to free r2 for an SValue first
To be able to load a long long value correctly on i386, gv() rely on the
fact that when get_reg() look at an SValue it tries first to free the
register in r2 and then r. More information about the context can be
found at
http://lists.nongnu.org/archive/html/tinycc-devel/2012-06/msg00017.html
and later at
http://lists.nongnu.org/archive/html/tinycc-devel/2012-07/msg00021.html
---
tccgen.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/tccgen.c b/tccgen.c
index d27bdba..71d0809 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -589,11 +589,11 @@ ST_FUNC int get_reg(int rc)
IMPORTANT to start from the bottom to ensure that we don't
spill registers used in gen_opi()) */
for(p=vstack;p<=vtop;p++) {
- r = p->r & VT_VALMASK;
+ /* look at second register (if long long) */
+ r = p->r2 & VT_VALMASK;
if (r < VT_CONST && (reg_classes[r] & rc))
goto save_found;
- /* also look at second register (if long long) */
- r = p->r2 & VT_VALMASK;
+ r = p->r & VT_VALMASK;
if (r < VT_CONST && (reg_classes[r] & rc)) {
save_found:
save_reg(r);
@@ -812,7 +812,8 @@ ST_FUNC int gv(int rc)
vtop[-1].r = r; /* save register value */
vtop->r = vtop[-1].r2;
}
- /* allocate second register */
+ /* Allocate second register. Here we rely on the fact that
+ get_reg() tries first to free r2 of an SValue. */
r2 = get_reg(rc2);
load(r2, vtop);
vpop();
--
1.7.10.4