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 target/69660] New: Microblaze break_handler and symbol `_interrupt_handler' is already defined


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69660

            Bug ID: 69660
           Summary: Microblaze break_handler and symbol
                    `_interrupt_handler' is already defined
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: minor
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: a_fisch at gmx dot de
  Target Milestone: ---

Hi all,

I tried to implement some low level routines for the microblaze target and used
some rarely used features of the microblaze GCC toolchain. 
When I tried to implement a break_handler and an interrupt_handler, I found
unexpected behavior and the emitted assembler output terminated compilation
with: Error: symbol `_interrupt_handler' is already defined

I am not familiar with bug reporting procedure, and I don't have a system,
which is ready to compile GCC to fix it myself. But I'll try my best.

The GCC Toolchain I used is part of the Xilinx Vivado 2015.4 SDK.

    d:\>mb-gcc --version
    mb-gcc (crosstool-NG 1.20.0) 4.9.2

I assume, that the following patch is introducing support for break_handler,
but is not completely correct: 
https://gcc.gnu.org/ml/gcc-patches/2014-05/msg00951.html

In the meantime I crosschecked different versions and found out, that the error
was introduced earlier. Part of the erroneous code pattern was introduced with
the first version in 2010. Afterwards it was copied and extended several times.
It is still present up to now (HEAD).


I used this example, which has an interrupt_handler and a break_handler within
the same compile unit:

// Invoke:
//  mb-gcc -save-temps Interrupt_u_BreakHandler.c
//  Command returns with the following error:
//    Interrupt_u_BreakHandler.s: Assembler messages:
//    Interrupt_u_BreakHandler.s:132: Error: symbol `_interrupt_handler' is
already defined
//
//   See assembler output in Interrupt_u_BreakHandler.s
//

void BreakH(void) __attribute__ ((break_handler)); // <-- Error triggered here
void BreakH(void) 
{
}

void __attribute__ ((interrupt_handler)) ISR(void) // <-- Together with this
{
}

int main(int argc, char **argv)
{
  return(0);
} 


It looks like the resulting function prolog in the assembler output for the
break_handler is wrong.


        .text
        .align  2
        .globl  _interrupt_handler //<-- I expected _break_handler here!
        .globl  BreakH
        .ent    _interrupt_handler //<-- I expected _break_handler here!
BreakH:
_interrupt_handler:                // <-- ???
_break_handler:
        .frame  r19,24,r15              # vars= 0, regs= 4, args= 0
        .mask   0x000e0800
        addik   r1,r1,-24
        swi     r15,r1,0
        swi     r11,r1,8
        swi     r17,r1,12
        swi     r18,r1,16
        swi     r19,r1,20
        mfs     r11,rmsr  #mfs
        swi     r11,r1,4
        addk    r19,r1,r0 #add movsi
        lwi     r15,r1,0
        addk    r1,r19,r0 #add movsi
        lwi     r11,r1,4
        mts     rmsr,r11  #mts
        lwi     r11,r1,8
        lwi     r17,r1,12
        lwi     r18,r1,16
        lwi     r19,r1,20
        addik   r1,r1,24
        rtbd    r16,8
        nop             # Unfilled delay slot

        .end    _break_handler              // <-- Epilog ok!!!
$Lfe1:
        .size   BreakH,$Lfe1-BreakH
        .align  2
        .globl  _interrupt_handler
        .globl  ISR
        .ent    _interrupt_handler
ISR:
_interrupt_handler:
        .frame  r19,24,r15              # vars= 0, regs= 4, args= 0
        .mask   0x000e0800
        addik   r1,r1,-24
        swi     r15,r1,0
        swi     r11,r1,8
        swi     r17,r1,12
        swi     r18,r1,16
        swi     r19,r1,20
        mfs     r11,rmsr  #mfs
        swi     r11,r1,4
        addk    r19,r1,r0 #add movsi
        lwi     r15,r1,0
        addk    r1,r19,r0 #add movsi
        lwi     r11,r1,4
        mts     rmsr,r11  #mts
        lwi     r11,r1,8
        lwi     r17,r1,12
        lwi     r18,r1,16
        lwi     r19,r1,20
        addik   r1,r1,24
        rtid    r14,0 
        nop             # Unfilled delay slot

        .end    _interrupt_handler

I tried to track the problem and found the following suspicious code within the
sources of the gcc toolchain:
(mb-gnu-20150907.tar.gz was the newest one I could find on the xilinx web site,
but I found the same files and code lines in the git repositories here.)

 
mb-gnu-20150907.tar.gz\mb-gnu-20150907.tar\microblaze_2015.3_sources\gcc\gcc\config\microblaze\microblaze.c

Line 2918: microblaze_function_prologue (FILE * file, HOST_WIDE_INT size
ATTRIBUTE_UNUSED)

  if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))//<-- Wrong! 
    fputs ("_interrupt_handler", file);
  else if (break_handler && strcmp (BREAK_HANDLER_NAME, fnname))//<-- Wrong!
    fputs ("_break_handler", file);
  else if (fast_interrupt && strcmp (FAST_INTERRUPT_NAME, fnname))//<--Wrong!
    fputs ("_fast_interrupt", file);
  else
    assemble_name (file, fnname);
  fputs ("\n", file);

strcmp(INTERRUPT_HANDLER_NAME, fnname) returns zero, if the strings match.
But the condition assumes the opposite!
This code pattern is used at least three times within the file
.\gcc\gcc\config\microblaze\microblaze.c. (look for BREAK_HANDLER_NAME)

In microblaze_function_epilogue() a different pattern is used, which seems to
be ok.

Who is going to correct this? I don't have a system to compile GCC.
But I could test a corrected compiler.

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