Article View: gnu.gcc.bug
Article #2382To volatile or not to volatile.
From: cire|eric
Date: Mon, 13 Mar 1989 01:13
Date: Mon, 13 Mar 1989 01:13
142 lines
4079 bytes
4079 bytes
That is the menace. Consider the fragment listed below. The struct foo1
is used to point at a descriptor of an i/o device. Now I've noticed two
points:
1) When the statement "c = *ptr->data" actually does retrieve the data
the assembly code "moveb a0@(1),d1" is used. "c" is an unsigned char.
Now this is certainly correct of the compiler to generate this because
the statement is being looked at as "c = (uchar) (*ptr->data)". However,
the desired intent is go get the volatile short *ptr->data and then
cast it to be an unsigned char.
I haven't seen the ANSI spec but my interpretation of volatile was
simply refetch this cell every time you use it. It strikes me that
it would be better if it were something like refetch this unsigned
short everytime you need it.
2) I've also noticed that the optimizer removes any references for
cells that are not used. When the fragment is compiled with -O
the reference at "A" below only remains because of the call to
forceuse. The reference at "B" disappears.
For this fragment this behaviour causes havoc. The intent at "B"
is to clear out a byte stream coming from the device but the
data register is never accessed. This is a common use of volatile.
For larger fragments of code whether or not the reference is
around is dependent on how the compiler views the code. This can
result in some very entertaining results.
Strikes me that perhaps the meaning of volatile should be always
fetch the cell as the defined type no matter what.
Thoughts?
-c
cire|eric
Eric B. Decker
cisco Systems
Menlo Park, California
email: cire@cisco.com
uSnail: 1360 Willow Rd., Menlo Park, CA 94025
Phone : (415) 326-1941
------------------------------------------------------------------------
test.c:
typedef struct foo1 {
volatile unsigned short *data;
volatile unsigned short *status;
} footype;
void forceuse(c)
unsigned char c;
{
int blah;
blah = c;
}
void test (ptr)
footype *ptr;
{
register unsigned int status;
register int flag;
register unsigned char c=0;
while ((status = *ptr->status) & 1) {
c = *ptr->data; /* <- A */
if (status & 128) {
while (*ptr->status & 1)
c = *ptr->data; /* <- B */
c = 0;
}
}
forceuse(c);
}
int main()
{
unsigned char buff[1024];
footype blah;
blah.data=(unsigned short *) &buff[0];
blah.status=(unsigned short *) &buff[2];
buff[3]=1;
buff[0]=0xAA;
buff[1]=0x55;
(void) test(&blah);
}
------------------------------------------------------------------------
compiling:
gcc -v -S -O -W test.c -o test_opt.s
gcc version 1.32
/usr/local/lib/gcc-cpp -v -undef -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__OPTIMIZE__ -D__HAVE_68881__ -Dmc68020 test.c /tmp/cca16995.cpp
GNU CPP version 1.32
/usr/local/lib/gcc-cc1 /tmp/cca16995.cpp -quiet -dumpbase test.c -O -W -version -o test_opt.s
GNU C version 1.32 (68k, MIT syntax) compiled by GNU C version 1.32.
------------------------------------------------------------------------
test_opt.s:
.globl _test
_test:
link a6,#0
moveml #0x2020,sp@-
movel a6@(8),a1
clrb d1
movel a1@(4),a2
clrl d2
jra L3
L9:
movel a1@,a0 <- fetch data, only here because of forceuse
moveb a0@(1),d1 <-
tstb d2
jge L3
movel a1@(4),a0
L6:
movew a0@,d0
btst #0,d0
jne L6 <- should be a reference to data here!
clrb d1
L3:
movew a2@,d0
movew d0,d2
btst #0,d2
jne L9
clrl d0
moveb d1,d0
movel d0,sp@-
jbsr _forceuse
moveml a6@(-8),#0x404
unlk a6
rts
Technical Details
Message-ID:
<8903130045.AA21334@prep.ai.mit.edu>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!watmath!uunet!tut.cis.ohio-state.edu!CISCO.COM!cireShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!watmath!uunet!tut.cis.ohio-state.edu!CISCO.COM!cire From: cire@CISCO.COM (cire|eric) Newsgroups: gnu.gcc.bug Subject: To volatile or not to volatile. Message-ID: <8903130045.AA21334@prep.ai.mit.edu> Date: 13 Mar 89 01:13:03 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 142