This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

c28x compiler 6.4.2 space optimization corrupts stack



The Optimizer of the cl2000 compiler seams to optimize out local variables, but still accesses them on stack leading to stack corruption and faults on return.

- cl2000 compiler Versions 6.4.2, 6.2.7, 6.2.10
- optimize for space (-ms)

Sample Code:

uint64_t DeviceSearch::find( uint16_t device_code )
{
  if ( !check_for_device_presence() )
    return NoDevices;

  m_master.write_byte( Command::SEARCH_ROM );

  if ( !check_for_device_of_family( device_code ) )
    return NoMatchingDevice;

  uint64_t address = read_device_address( device_code );
  if ( address_is_error( address ) )
    return address;

  if ( !address_crc_valid( address ) )
    return AddressCrcError;

  return address;
}

uint64_t DeviceSearch::read_device_address( uint16_t device_code )
{
  uint64_t address = device_code;
  for ( int i=8; i<64; i++ )
  {
    Master::AddressBits ab = m_master.one_wire_triplet( 0 );
    if ( ab == Master::AB_ONE )
      address |= (1ull)<<i;
    if ( ab == Master::AB_NONE )
      return NoMatchingDevice;
    if ( ab == Master::AB_BOTH )
      return MultipleMatchingDevices;
  }
  return address;
}

- works if complied without optimization
- if compiled with -ms the "address" vairable in booth functions seams to be optimized away
- stepping in the debugger shows nonsensical address values
- return from find ends up at the wrong address
- making address volatile in read_device_address to prevent optimization off the variable seams to be a work around

- please contact me via email for a sample project which triggers the problem.

  • Dirk Harms said:
    please contact me via email for a sample project which triggers the problem.

    It would be better if you sent me a private message via the forum, and attached the project to that message.  Hover your mouse over my avatar or screen name.  A dialog box pops up.  Click on Send a private message.  A message compose interface comes up.  Use the paper clip icon to attach the project .zip file.

    Thanks and regards,

    -George

  • Thank you for submitting a test case.  I can reproduce the stack corruption you describe.  

    Code generated for the problem function has these instructions at the beginning ...

    MOVB XAR0,#6 ; [CPU_]
    FFC XAR7,_prolog_c28x_2 ; [CPU_]

    The function _prolog_c28x_2 pushes XAR1, XAR2, and XAR3 on the stack. It also adds 6 to SP. In total, SP increases by 12.

    At the end of the function none of XAR1, XAR2, and XAR3 are restored. And only 6 is subtracted from SP. The net result is XAR1, XAR2, and XAR3 are corrupted and SP is 6 off.

    I submitted SDSCM00051517 in the SDOWP system to have this problem investigated.  Feel free to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George

  • Any updates on this issue?

  • This issue is fixed in version 6.4.3.  Every release includes a file named DefectHistory.txt with a record of the issues fixed in that release.  Here is the entry for this particular issue ...

    -------------------------------------------------------------------------------
    FIXED SDSCM00051517
    -------------------------------------------------------------------------------
    
    Summary            : Stack is corrupted when --opt_for_space is used
    
    Fixed in           : 6.4.3
    Severity           : S2 - Major
    Affected Component : Code Generator
    
    Release Notes:
      When optimize for size is used on C2000 (-ms, --opt_for_space, -mf0), the
      prolog and/or epilog for a function may be replaced with library routines
      such as _prolog_c28x_2. If a prolog from the library is used, but an
      epilog from the library is not, this may result in not properly restoring
      all saved registers from the stack.
      
      Defect occurs in C2000 Compiler versions: 5.2.0B1 - 5.2.15, 6.0.0B1 - 6.0.6,
      6.1.0B1 - 6.1.10, 6.2.0B1 - 6.2.11, 6.4.2
    
    Workaround:
      Disable/lower optimization for size.
      Note: Normal optimization levels (-o[0-4]) do not affect this bug.
            Lowering or removing the use of -ms (--opt_for_space) and -mf to favor
            performance over size will alleviate this behavior.
    

    Thanks and regards,

    -George

  • Hi George,

    OK Thanks. The reason I was asking is related to restore problems with XAR0 and XAR1 on the 28377D using only assembly.  Looks like during an interrupt save that only the lower word of XAR0 and XAR1 are saved to the stack.  So if the interrupting routing modifies the upper word of XAR0 and/or XAR1 than then upper word will not be restored properly.  Is there a way to resolve this? Manually save/restore the upper word maybe?

    Thanks

    -Tom

  • Thomas Keller2 said:
    The reason I was asking is related to restore problems with XAR0 and XAR1 on the 28377D using only assembly. 

    I am not familiar with this detail of the C2000 CPU.  I suggest you start a new thread about it in the C2000 device forum.

    Thanks and regards,

    -George

  • Is it the interrupt routine modifying the high part of XAR0/1 and failing to restore it? Is this interrupt routine written in C? If so, this is another bug.
  • Yes the interrupting routine is modifying the high word of XAR0/1. The interrupt save mechanism does not save the upper word of XAR0/1 to the stack that I can see so it has no chance of restoring it. This is all reproduced with assembly. Is this a known issue?
  • If your interrupt routine is written in hand-coded assembly code, it is your responsibility to save those registers explicitly.  Here is an example of a full C calling convention context save:

    _isrX:
            ASP       
            PUSH      AR1H:AR0H
            SPM       0                     
            MOVL      *SP++,XT              
            MOVL      *SP++,XAR4            
            MOVL      *SP++,XAR5            
            MOVL      *SP++,XAR6            
            MOVL      *SP++,XAR7            
            CLRC      PAGE0,OVM            
            CLRC      AMODE
            ; At this point, everything is saved                 
            LCR       #_do_some_work
            ; Done; now restore the registers
            MOVL      XAR7,*--SP            
            MOVL      XAR6,*--SP            
            MOVL      XAR5,*--SP            
            MOVL      XAR4,*--SP            
            MOVL      XT,*--SP              
            POP       AR1H:AR0H             
            NASP      
            IRET      
    

    Note the "PUSH AR1H:AR0H" instruction; this saves the high part of XAR0/XAR1.

  • Thanks for looking into this and helping me understand what I need to do.   I was looking at Table 3-4 in SPRU430F and saw that AR0 and AR1 are automatically saved.  Maybe that should be AR0L and AR1L for clarity?  

  • Thomas Keller2 said:
    I was looking at Table 3-4 in SPRU430F and saw that AR0 and AR1 are automatically saved.  Maybe that should be AR0L and AR1L for clarity?  

    We compiler experts are not responsible for that manual.  But I let the relevant team know about this problem, and they filed a ticket to address it in a future revision.

    Thanks and regards,

    -George