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

Reply via email to