Alternative fix for "Incorrect function call code on ARMv6"
"make test" crashes without that "save_regs()".
This partially reverts
commit 49d3118621.
Found another solution: In a 2nd pass Just look if
any of the argument registers has been saved again,
and restore if so.
This commit is contained in:
11
arm-gen.c
11
arm-gen.c
@ -1047,6 +1047,7 @@ static int copy_params(int nb_args, struct plan *plan, int todo)
|
|||||||
{
|
{
|
||||||
int size, align, r, i, nb_extra_sval = 0;
|
int size, align, r, i, nb_extra_sval = 0;
|
||||||
struct param_plan *pplan;
|
struct param_plan *pplan;
|
||||||
|
int pass = 0;
|
||||||
|
|
||||||
/* Several constraints require parameters to be copied in a specific order:
|
/* Several constraints require parameters to be copied in a specific order:
|
||||||
- structures are copied to the stack before being loaded in a reg;
|
- structures are copied to the stack before being loaded in a reg;
|
||||||
@ -1063,8 +1064,14 @@ static int copy_params(int nb_args, struct plan *plan, int todo)
|
|||||||
- parameters assigned to VFP regs be copied before structures assigned to
|
- parameters assigned to VFP regs be copied before structures assigned to
|
||||||
VFP regs as the copy might use an even numbered VFP reg that already
|
VFP regs as the copy might use an even numbered VFP reg that already
|
||||||
holds part of a structure. */
|
holds part of a structure. */
|
||||||
|
again:
|
||||||
for(i = 0; i < NB_CLASSES; i++) {
|
for(i = 0; i < NB_CLASSES; i++) {
|
||||||
for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
|
for(pplan = plan->clsplans[i]; pplan; pplan = pplan->prev) {
|
||||||
|
|
||||||
|
if (pass
|
||||||
|
&& (i != CORE_CLASS || pplan->sval->r < VT_CONST))
|
||||||
|
continue;
|
||||||
|
|
||||||
vpushv(pplan->sval);
|
vpushv(pplan->sval);
|
||||||
pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
|
pplan->sval->r = pplan->sval->r2 = VT_CONST; /* disable entry */
|
||||||
switch(i) {
|
switch(i) {
|
||||||
@ -1170,6 +1177,10 @@ static int copy_params(int nb_args, struct plan *plan, int todo)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* second pass to restore registers that were saved on stack by accident */
|
||||||
|
if (++pass < 2)
|
||||||
|
goto again;
|
||||||
|
|
||||||
/* Manually free remaining registers since next parameters are loaded
|
/* Manually free remaining registers since next parameters are loaded
|
||||||
* manually, without the help of gv(int). */
|
* manually, without the help of gv(int). */
|
||||||
save_regs(nb_args);
|
save_regs(nb_args);
|
||||||
|
|||||||
5
tccgen.c
5
tccgen.c
@ -861,6 +861,11 @@ ST_FUNC int gv(int rc)
|
|||||||
#endif
|
#endif
|
||||||
if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
|
if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
|
||||||
(vtop->r & VT_LVAL)) {
|
(vtop->r & VT_LVAL)) {
|
||||||
|
/* We do not want to modifier the long long
|
||||||
|
pointer here, so the safest (and less
|
||||||
|
efficient) is to save all the other registers
|
||||||
|
in the stack. XXX: totally inefficient. */
|
||||||
|
save_regs(1);
|
||||||
/* load from memory */
|
/* load from memory */
|
||||||
vtop->type.t = load_type;
|
vtop->type.t = load_type;
|
||||||
load(r, vtop);
|
load(r, vtop);
|
||||||
|
|||||||
Reference in New Issue
Block a user