#1081 SIGSEGV Compiling pointer offset

closed-fixed
nobody
5
2013-05-25
2006-03-15
xander
No

SDCC : pic16/pic14 2.5.5 #1226 (Mar 15 2006) (MSVC)

sdcc crashes when compiling an offset to a pointer.
Compiling the following code will cause the problem:

typedef struct _BDT
{
char Stat;
char Cnt;
unsigned int ADDR;
} BDT; //Buffer Descriptor Table

char *inPtr;
char x;

BDT at 0x0400 ep0Bo;

static void SetFeature(char e)
{
char endpointNum = e;
inPtr = (char *)&ep0Bo + (endpointNum * 8);
}

Command line used to do the compile:
sdcc -mpic16 -c badptr1.c
Output is:
Caught signal 11: SIGSEGV

Note that if you replace "ep0Bo" by "x" in the
function SetFeature(), sdcc will compile.
Eliminating the "at 0x0400" from the declaration of
ep0Bo will also result in compilation. Appears the
use of a fixed address in the variable declaration
leads to the problem.

This problem was not in build 1209 so it was
introduced somewhere between 1209 and 1226.

Xander

Discussion

  • Raphael Neider

    Raphael Neider - 2006-03-16

    Logged In: YES
    user_id=1115835

    Fixed in SDCC #1227, src/pic16/genarith.c 1.27.
    For more compact code you might want to use

    static void SetFeature(char e)
    {
    unsigned char endpointNum = e;
    inPtr = (char *)&ep0Bo + (endpointNum * 8u);
    }

    (i.e. unsigned char and 8u to force unsigned multiplication).

    Regards,
    Raphael

     
  • Raphael Neider

    Raphael Neider - 2006-03-16
    • milestone: --> fixed
    • assigned_to: nobody --> tecodev
    • status: open --> closed-fixed
     
  • Nobody/Anonymous

    Logged In: NO

    Waiting for fix in CVS.

    BTW, using this:
    inPtr = (char *)&ep0Bo + (endpointNum * 8u);

    As described below adds quite a bit of code to the
    resulting hex file as a direct result of the "8u" instead
    of "8". Looks like an extra 32 bytes each time. The
    actual code is all "unsigned char" - the "char" in the
    example was just to try to make it as small as possible.

    Xander

     
  • Bernhard Held

    Bernhard Held - 2006-03-16

    Logged In: YES
    user_id=203539

    "8" is indeed better than "8u".

    Why?

    "8" is an integer constant, but sdcc stores it with type
    "unsigned char". This is possible because if a promotion is
    required sdcc will promote it to "signed int". If the
    promotion can be omitted, sdcc will emit better code because
    of the unsigned type.

    However "8u" is an unsigned integer constant, which must be
    store with type "unsigned int". It's not possible to give it
    the type "unsigned char", because a promotion might change
    it to "signed int" and the correct signedness gets lost.

    The promotion rules are hairy, take good care!!

     
  • Raphael Neider

    Raphael Neider - 2006-03-16
    • assigned_to: tecodev --> nobody
     
  • Raphael Neider

    Raphael Neider - 2006-03-16

    Logged In: YES
    user_id=1115835

    Hmmm...
    My consideration here is that (char * literal) yields a
    signed entity of size int (2 bytes).
    As a (char*) is 3 bytes, I need to expand the left addend to
    3 bytes and---as it is now signed (SPEC_USIGN(left) == 0)
    with left being the result of (endpointNum * 8)---this
    incurs considerable overhead compared to expanding it always
    with zero as in the unsigned case, using (unsigned char *
    unsigned_lit).

    PIC16-Code (signed case, endpoint*8 in r0x01|r0x00):
    ; low byte of _inPtr
    movfw r0x00
    movwf _inPtr
    ; 2nd byte of _inPtr
    movlw 0x04
    addwf r0x01
    movwf (_inPtr+1)
    ; 3rd byte of _inPtr, propagate carry
    movlw 0x00
    clrf (_inPtr+2)
    btfsc r0x01,7
    setf (_inPtr+2)
    addwfc (_inPtr+2)

    unsigned case goes down to
    ; 3rd byte
    movlw 0x00
    clrf (_inPtr+2)
    addwfc (_inPtr+2)

    So, inspect the generated code and compare signed vs.
    unsigned cases if need be.

    Regards,
    Raphael

     
  • Bernhard Held

    Bernhard Held - 2006-03-20

    Logged In: YES
    user_id=203539

    Ok, I've to admit that my reply was very 51 oriented, and my
    statements might be wrong for other micros. The 51 comes
    with a 8x8->16 bit unsigned multiplication, which would be
    very effective in this example.
    The current "behaviour" of sdcc doning 8x8 multiplications
    is optimized for the 51. If this isn't optimal for other
    ports just let me know.

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks