This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: bug in arm-elf-gcc
- To: "Vadim Lebedev" <vlebedev at aplio dot fr>
- Subject: Re: bug in arm-elf-gcc
- From: Richard Earnshaw <rearnsha at arm dot com>
- Date: Fri, 19 May 2000 15:02:56 +0100
- Cc: gcc-bugs at gcc dot gnu dot org, rth at cygnus dot com
- Cc: rearnsha at arm dot com
- Organization: ARM Ltd.
- Reply-To: rearnsha at arm dot com
>
> The following code:
>
> ---------------
> /* lbtest.c */
> void callit1(void*);
>
> extern __inline__ void test()
> {
> __label__ l1;
>
> callit1(&&l1);
>
> l1:
>
> }
>
>
> void dotest()
> {
> test();
> }
> [generates a bad label reference]
This occurs because we don't scan for label references in the insns that
form a call placeholder.
Please try this patch.
Note, I have not been able to bootstrap this change because my normal
machine is currently down with a dead hard disk.
* flow.c (find_label_refs): New function.
(find_basic_blocks_1): Call it for each alternative of a call
placeholder.
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.285
diff -u -p -r1.285 flow.c
--- flow.c 2000/05/12 16:26:13 1.285
+++ flow.c 2000/05/19 13:56:10
@@ -309,6 +309,7 @@ struct propagate_block_info
/* Forward declarations */
static int count_basic_blocks PARAMS ((rtx));
static void find_basic_blocks_1 PARAMS ((rtx));
+static rtx find_label_refs PARAMS ((rtx, rtx));
static void clear_edges PARAMS ((void));
static void make_edges PARAMS ((rtx));
static void make_label_edge PARAMS ((sbitmap *, basic_block,
@@ -532,6 +533,50 @@ count_basic_blocks (f)
return count;
}
+/* Scan a list of insns for labels referrred to other than by jumps.
+ This is used to scan the alternatives of a call placeholder. */
+static rtx find_label_refs (f, lvl)
+ rtx f;
+ rtx lvl;
+{
+ rtx insn;
+
+ for (insn = f; insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ rtx note;
+
+ /* Make a list of all labels referred to other than by jumps
+ (which just don't have the REG_LABEL notes).
+
+ Make a special exception for labels followed by an ADDR*VEC,
+ as this would be a part of the tablejump setup code.
+
+ Make a special exception for the eh_return_stub_label, which
+ we know isn't part of any otherwise visible control flow. */
+
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_LABEL)
+ {
+ rtx lab = XEXP (note, 0), next;
+
+ if (lab == eh_return_stub_label)
+ ;
+ else if ((next = next_nonnote_insn (lab)) != NULL
+ && GET_CODE (next) == JUMP_INSN
+ && (GET_CODE (PATTERN (next)) == ADDR_VEC
+ || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
+ ;
+ else if (GET_CODE (lab) == NOTE)
+ ;
+ else
+ lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
+ }
+ }
+
+ return lvl;
+}
+
/* Find all basic blocks of the function whose first insn is F.
Collect and return a list of labels whose addresses are taken. This
@@ -672,9 +717,15 @@ find_basic_blocks_1 (f)
/* If this is a call placeholder, record its tail recursion
label, if any. */
- if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER
- && XEXP (PATTERN (insn), 3) != NULL_RTX)
- trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
+ if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
+ {
+ /* Scan each of the alternatives for label refs. */
+ lvl = find_label_refs (XEXP (PATTERN (insn), 0), lvl);
+ lvl = find_label_refs (XEXP (PATTERN (insn), 1), lvl);
+ lvl = find_label_refs (XEXP (PATTERN (insn), 2), lvl);
+ if (XEXP (PATTERN (insn), 3) != NULL_RTX)
+ trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
+ }
/* If there is an EH region or rethrow, we have an edge. */
if ((eh_list && region > 0)