diff options
author | Andrew Pinski <andrew.pinski@oss.qualcomm.com> | 2025-08-18 13:33:59 -0700 |
---|---|---|
committer | Andrew Pinski <andrew.pinski@oss.qualcomm.com> | 2025-08-19 08:55:14 -0700 |
commit | 6ece2d7274059265468833fb491db44bd90de72a (patch) | |
tree | 24c07034d5ecafb0f7833d50f770cca976bbbca1 | |
parent | 0ab1e31807a19d699c462937ca639718360eac0c (diff) | |
download | gcc-6ece2d7274059265468833fb491db44bd90de72a.zip gcc-6ece2d7274059265468833fb491db44bd90de72a.tar.gz gcc-6ece2d7274059265468833fb491db44bd90de72a.tar.bz2 |
middle-end: Fix malloc like functions when calling with void "return" [PR120024]
When expanding malloc like functions, we copy the return register into a temporary
and then mark that temporary register with a noalias regnote and the alignment.
This works fine unless you are calling the function with a return type of void.
At this point then the valreg will be null and a crash will happen.
A few cleanups are included in this patch because it was easier to do the fix
with the cleanups added.
The start_sequence/end_sequence for ECF_MALLOC is no longer needed; I can't tell
if it was ever needed.
The emit_move_insn function returns the last emitted instruction anyways so
there is no reason to call get_last_insn as we can just use the return value
of emit_move_insn. This has been true since this code was originally added
so I don't understand why it was done that way beforehand.
Bootstrapped and tested on x86_64-linux-gnu.
PR middle-end/120024
gcc/ChangeLog:
* calls.cc (expand_call): Remove start_sequence/end_sequence
for ECF_MALLOC.
Check valreg before deferencing it when it comes to malloc like
functions. Use the return value of emit_move_insn instead of
calling get_last_insn.
gcc/testsuite/ChangeLog:
* gcc.dg/torture/malloc-1.c: New test.
* gcc.dg/torture/malloc-2.c: New test.
Signed-off-by: Andrew Pinski <andrew.pinski@oss.qualcomm.com>
-rw-r--r-- | gcc/calls.cc | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/malloc-1.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/malloc-2.c | 12 |
3 files changed, 28 insertions, 13 deletions
diff --git a/gcc/calls.cc b/gcc/calls.cc index 2711c4e..bb8a6d0 100644 --- a/gcc/calls.cc +++ b/gcc/calls.cc @@ -3235,11 +3235,6 @@ expand_call (tree exp, rtx target, int ignore) if (pass) precompute_arguments (num_actuals, args); - /* Now we are about to start emitting insns that can be deleted - if a libcall is deleted. */ - if (pass && (flags & ECF_MALLOC)) - start_sequence (); - /* Check the canary value for sibcall or function which doesn't return and could throw. */ if ((pass == 0 @@ -3771,25 +3766,23 @@ expand_call (tree exp, rtx target, int ignore) valreg = gen_rtx_REG (TYPE_MODE (rettype), REGNO (valreg)); } - if (pass && (flags & ECF_MALLOC)) + /* If the return register exists, for malloc like + function calls, mark the return register with the + alignment and noalias reg note. */ + if (pass && (flags & ECF_MALLOC) && valreg) { rtx temp = gen_reg_rtx (GET_MODE (valreg)); - rtx_insn *last, *insns; + rtx_insn *last; /* The return value from a malloc-like function is a pointer. */ if (TREE_CODE (rettype) == POINTER_TYPE) mark_reg_pointer (temp, MALLOC_ABI_ALIGNMENT); - emit_move_insn (temp, valreg); + last = emit_move_insn (temp, valreg); /* The return value from a malloc-like function cannot alias anything else. */ - last = get_last_insn (); add_reg_note (last, REG_NOALIAS, temp); - - /* Write out the sequence. */ - insns = end_sequence (); - emit_insn (insns); valreg = temp; } diff --git a/gcc/testsuite/gcc.dg/torture/malloc-1.c b/gcc/testsuite/gcc.dg/torture/malloc-1.c new file mode 100644 index 0000000..ba24153 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/malloc-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* PR middle-end/120024 */ + +void *f(unsigned) __attribute__((malloc)); +void g() +{ + void *(*g)(unsigned) = f; + void (*h)(unsigned) = (void (*)(unsigned))g; + h(1); +} diff --git a/gcc/testsuite/gcc.dg/torture/malloc-2.c b/gcc/testsuite/gcc.dg/torture/malloc-2.c new file mode 100644 index 0000000..8eeca9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/malloc-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* PR middle-end/120024 */ + +void *f(unsigned) __attribute__((malloc)); +void h1(void); +void g(void) +{ + void *(*g)(unsigned) = f; + void (*h)(unsigned) = (void (*)(unsigned))g; + h(1); + h1(); +} |