[Bug target/69660] New: Microblaze break_handler and symbol `_interrupt_handler' is already defined
a_fisch at gmx dot de
gcc-bugzilla@gcc.gnu.org
Wed Feb 3 21:57:00 GMT 2016
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.
More information about the Gcc-bugs
mailing list