This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/20937] New: BLK ptr's loosing original ptr's static-constant readonly attribute.


The following example uses a minor modification of avr's avr.c config file to
identify readonly static constant data memory references using MEM_READONLY_P
and then simply emits a load-program-memory "lpm" instruction in lieu of a
load-data-memory "ld" instruction sequence (as a step toward enabling static data
to be accessed directly from the target's program ROM space vs. having to otherwise
redundantly copy all declared static data into the extreamly limited data RAM space.

[ Being able to allocate and direcly access static const data from a target's ROM is
  a very important feature for an embedded compiler to support, as for good or bad
  high volume small embedded taget's RAM is typically only a small fraction of the
  size of their program ROM size as RAM typically costs 4x as much; and often
  requires specialzed instructions to access data from program ROM, therefore such
  references need to be identifiable during code generation, which GCC seems to be
  largely already capable of, with a few minor caviots, to enable direct static data access.]

The following was discovered: (using 4.1 as of 2004-04-09, i.e. yesterday)

- direct static constant string, array, and structure data references are detected without any problems.

- inlined function references seem to loose the readonly attribute properly associated with
   static constant readonly string data references, and improperly orders volitile array references after
   coresponding volitile stores; but seems to handle structure data accesses properly.

- BLK ptr's used to move structure data (and possibly string data) improperly looses the readonly
   attribute originally correctly associated with the memory references to static constant data.

- __FUNCTION__ which is supposed to designate a static constant string, isn't doing so properly.

- function parameters need to accept the specification of a pointer to a static storage qualifed type,
  as opposed to specifying that the pointer parameter itself has a storage qualification, which isn't
  allowed; thereby propose that:

   char static * funct (char static * cp), specifies a function which accepts a pointer to a static char,
   returns a pointer to a static char; not that the pointer's are static storage qualifed themselfs.

- and finally, for some reason inlined funtions which are specifed as returning char, are allocating
  and treating the return type as an int, which seems basiclly both unnessisary and likely wrong.

---

Example program: main.c

#if 0 /* Enable to force allocation into ".text" program memory section */
 #define ROM __attribute__((__progmem__)) /* Retains static data in ROM */
#else
 #define ROM
#endif

typedef struct {
  char a; char b; char c; char d; char e; char f; char g; char h;
} struct_t;

char foo( ROM const char * s )
{
  return s[0] ;
}

char bar( ROM const struct_t * t )
{
  return t->a ;
}

char name( void )
{
  return ROM __FUNCTION__[0];
}

int main ( void )
{

  volatile char v;
 
  ROM volatile static const char c[8] = {1, 2, 3, 4, 5, 6, 7, 8};
  
  ROM volatile static const char s[8] = "(string)";

  ROM volatile static const struct_t t = {1, 2, 3, 4, 5, 6, 7, 8};
  
  volatile struct_t vt = t;
  
  v = c[0];
  
  v = s[0];
    
  v = t.a;
      
  v = foo( c );
  
  v = foo( s );
  
  v = bar( &t );
  
  v = name();
  
  return 0;
}

---

Example result: main.lss (annotated with error comments):

main.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .data         0000001e  00800100  00000122  000001b6  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  1 .text         00000122  00000000  00000000  00000094  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          00000000  0080011e  00000140  000001d4  2**0
                  ALLOC
  3 .noinit       00000000  0080011e  0080011e  000001d4  2**0
                  CONTENTS
  4 .eeprom       00000000  00810000  00810000  000001d4  2**0
                  CONTENTS
  5 .stab         000005c4  00000000  00000000  000001d4  2**2
                  CONTENTS, READONLY, DEBUGGING
  6 .stabstr      00000481  00000000  00000000  00000798  2**0
                  CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:

00000000 <__vectors>:
   0:	0c 94 46 00 	jmp	0x8c <__ctors_end>
   4:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
   8:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
   c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  10:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  14:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  18:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  1c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  20:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  24:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  28:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  2c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  30:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  34:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  38:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  3c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  40:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  44:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  48:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  4c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  50:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  54:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  58:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  5c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  60:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  64:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  68:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  6c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  70:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  74:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  78:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  7c:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  80:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  84:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>
  88:	0c 94 61 00 	jmp	0xc2 <__bad_interrupt>

0000008c <__ctors_end>:
  8c:	11 24       	eor	r1, r1
  8e:	1f be       	out	0x3f, r1	; 63
  90:	cf ef       	ldi	r28, 0xFF	; 255
  92:	d0 e1       	ldi	r29, 0x10	; 16
  94:	de bf       	out	0x3e, r29	; 62
  96:	cd bf       	out	0x3d, r28	; 61

00000098 <__do_copy_data>:
  98:	11 e0       	ldi	r17, 0x01	; 1
  9a:	a0 e0       	ldi	r26, 0x00	; 0
  9c:	b1 e0       	ldi	r27, 0x01	; 1
  9e:	e2 e2       	ldi	r30, 0x22	; 34
  a0:	f1 e0       	ldi	r31, 0x01	; 1
  a2:	02 c0       	rjmp	.+4      	; 0xa8 <.do_copy_data_start>

000000a4 <.do_copy_data_loop>:
  a4:	05 90       	lpm	r0, Z+      ; (disabled if all static data ROMed)
  a6:	0d 92       	st	X+, r0

000000a8 <.do_copy_data_start>:
  a8:	ae 31       	cpi	r26, 0x1E	; 30
  aa:	b1 07       	cpc	r27, r17
  ac:	d9 f7       	brne	.-10     	; 0xa4 <.do_copy_data_loop>

000000ae <__do_clear_bss>:
  ae:	11 e0       	ldi	r17, 0x01	; 1
  b0:	ae e1       	ldi	r26, 0x1E	; 30
  b2:	b1 e0       	ldi	r27, 0x01	; 1
  b4:	01 c0       	rjmp	.+2      	; 0xb8 <.do_clear_bss_start>

000000b6 <.do_clear_bss_loop>:
  b6:	1d 92       	st	X+, r1

000000b8 <.do_clear_bss_start>:
  b8:	ae 31       	cpi	r26, 0x1E	; 30
  ba:	b1 07       	cpc	r27, r17
  bc:	e1 f7       	brne	.-8      	; 0xb6 <.do_clear_bss_loop>
  be:	0c 94 6e 00 	jmp	0xdc <main>

000000c2 <__bad_interrupt>:
  c2:	0c 94 00 00 	jmp	0x0 <__heap_end>

000000c6 <foo>:
  char a; char b; char c; char d; char e; char f; char g; char h;
} struct_t;

char foo( ROM const char * s )         ; (error: needs static const * qual!)
{
  c6:	fc 01       	movw	r30, r24
  c8:	80 81       	ld	r24, Z     ; (error: needs static const * qual!)
  return s[0] ;
}
  ca:	99 27       	eor	r25, r25   ; (error: returning char not int!)
  cc:	08 95       	ret

000000ce <bar>:

char bar( ROM const struct_t * t )      ; (error: needs static const * qual!)
{
  ce:	fc 01       	movw	r30, r24
  d0:	80 81       	ld	r24, Z      ; (error: needs static const * qual!)
  return t->a ;
}
  d2:	99 27       	eor	r25, r25    ; (error: returning char not int!)
  d4:	08 95       	ret

000000d6 <name>:

char name( void )
{
  return ROM __FUNCTION__[0];
}
  d6:	8e e6       	ldi	r24, 0x6E	; 110 (error: should be static const!)
  d8:	90 e0       	ldi	r25, 0x00	; 0   (error: returning char not int!)
  da:	08 95       	ret

000000dc <main>:

int main ( void )
{
  dc:	c6 ef       	ldi	r28, 0xF6	; 246
  de:	d0 e1       	ldi	r29, 0x10	; 16
  e0:	de bf       	out	0x3e, r29	; 62
  e2:	cd bf       	out	0x3d, r28	; 61

  volatile char v;
 
  ROM volatile static const char c[8] = {1, 2, 3, 4, 5, 6, 7, 8};
  
  ROM volatile static const char s[8] = "(string)";

  ROM volatile static const struct_t t = {1, 2, 3, 4, 5, 6, 7, 8};
  
  volatile struct_t vt = t;
  e4:	de 01       	movw	r26, r28
  e6:	12 96       	adiw	r26, 0x02	; 2
  e8:	e5 e0       	ldi	r30, 0x05	; 5
  ea:	f1 e0       	ldi	r31, 0x01	; 1
  ec:	88 e0       	ldi	r24, 0x08	; 8
  ee:	01 90       	ld	r0, Z+      ; (error: BLK ptr looses qualifiers!)
  f0:	0d 92       	st	X+, r0
  f2:	81 50       	subi	r24, 0x01	; 1
  f4:	e1 f7       	brne	.-8      	; 0xee <main+0x12>
  
  v = c[0];
  f6:	84 91       	lpm	r24, Z      ; (correct: static const data access!)
  f8:	89 83       	std	Y+1, r24	; 0x01
  
  v = s[0];
  fa:	84 91       	lpm	r24, Z      ; (correct: static const data access!)
  fc:	89 83       	std	Y+1, r24	; 0x01
    
  v = t.a;
  fe:	84 91       	lpm	r24, Z      ; (correct: static const data access!)
 100:	89 83       	std	Y+1, r24	; 0x01
 102:	84 91       	lpm	r24, Z		; (error: second volatile access!)
      
  v = foo( c );
 104:	99 27       	eor	r25, r25    ; (error: returning char not int!)
 106:	89 83       	std	Y+1, r24	; 0x01
 108:	84 91       	lpm	r24, Z      ; (error: lpm after volatile store!)
  
  v = foo( s );
 10a:	99 27       	eor	r25, r25    ; (error: returning char not int!)
 10c:	89 83       	std	Y+1, r24	; 0x01 (error: s[0] == "(" via lpm!)

  v = bar( &t );
 10e:	84 91       	lpm	r24, Z
 110:	99 27       	eor	r25, r25	; (error: returning char not int!)
 112:	89 83       	std	Y+1, r24	; 0x01
  
  v = name();
 114:	8e e6       	ldi	r24, 0x6E	; 110 (error: __FUNCTION__ should be
 116:	89 83       	std	Y+1, r24	; 0x01 declared as static const data!)
  
  return 0;
}
 118:	80 e0       	ldi	r24, 0x00	; 0
 11a:	90 e0       	ldi	r25, 0x00	; 0
 11c:	0c 94 90 00 	jmp	0x120 <_exit>

00000120 <_exit>:
 120:	ff cf       	rjmp	.-2      	; 0x120 <_exit>

---

Example required avr.c.patch:

--- gcc/gcc/config/avr/avr.c        Sun Mar 20 16:12:08 2005
+++ gcc/gcc/config/avr/avr.c        Sun Apr 10 18:44:03 2005
@@ -1803,6 +1803,9 @@ out_movqi_r_mr (rtx insn, rtx op[], int 
   rtx x = XEXP (src, 0);
   int dummy;
   
+  if (MEM_READONLY_P(src))                          //++
+    return (AS2 (lpm,%A0,Z));                       //++
+           
   if (!l)
     l = &dummy;
   
@@ -1870,6 +1873,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
      for correct operation with 16-bit I/O registers.  */
   int mem_volatile_p = MEM_VOLATILE_P (src);
   int tmp;
+  
+  if (MEM_READONLY_P(src))                          //++
+    return (AS2 (lpm,%A0,Z));                       //++
 
   if (!l)
     l = &tmp;
@@ -2021,6 +2027,9 @@ out_movsi_r_mr (rtx insn, rtx op[], int 
   int reg_base = true_regnum (base);
   int tmp;
 
+  if (MEM_READONLY_P(src))                          //++
+    return (AS2 (lpm,%A0,Z));                       //++
+
   if (!l)
     l = &tmp;
   
@@ -2182,6 +2191,9 @@ out_movsi_mr_r (rtx insn, rtx op[], int 
   int reg_src = true_regnum (src);
   int tmp;
   
+  if (MEM_READONLY_P(dest))                         //++
+    fatal_insn ("write readonly insn:",insn);       //++
+           
   if (!l)
     l = &tmp;
   
@@ -2485,6 +2497,9 @@ out_movqi_mr_r (rtx insn, rtx op[], int 
   rtx src = op[1];
   rtx x = XEXP (dest, 0);
   int dummy;
+  
+  if (MEM_READONLY_P(dest))                         //++
+    fatal_insn ("write readonly insn:",insn);       //++
 
   if (!l)
     l = &dummy;
@@ -2565,6 +2580,9 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
      for correct operation with 16-bit I/O registers.  */
   int mem_volatile_p = MEM_VOLATILE_P (dest);
   int tmp;
+  
+  if (MEM_READONLY_P(dest))                         //++
+    fatal_insn ("write readonly insn:",insn);       //++
 
   if (!l)
     l = &tmp;
----

-- 
           Summary: BLK ptr's loosing original ptr's static-constant
                    readonly attribute.
           Product: gcc
           Version: 4.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: schlie at comcast dot net
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: ppc-apple-darwin
  GCC host triplet: ppc-apple-darwin
GCC target triplet: avr-none-none


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20937


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]