Bug 1657135 - unify integer and floating-point argument allocation r=xpcom-reviewers,nika

Through some sleight-of-hand, we can treat argument allocation in aarch64's
xptcinvoke exactly the same for integer and floating-point arguments.  This
change isn't so important now, but it centralizes the allocation of stack
slots, which is important for making this code handle Apple's calling
conventions.

Depends on D87005

Differential Revision: https://phabricator.services.mozilla.com/D87006
This commit is contained in:
Nathan Froyd 2020-08-19 04:06:29 +00:00
Родитель 83607c3e88
Коммит 968a2e4064
1 изменённых файлов: 30 добавлений и 52 удалений

Просмотреть файл

@ -24,69 +24,47 @@
#endif
/*
* Allocation of integer function arguments initially to registers r1-r7
* and then to stack. Handling of 'that' argument which goes to register r0
* is handled separately and does not belong here.
* Allocation of function arguments to their appropriate place in registers
* if possible and then to the stack. Handling of 'that' argument which
* goes to register r0 is handled separately and does not belong here.
*
* 'ireg_args' - pointer to the current position in the buffer,
* corresponding to the register arguments
* 'stack_args' - pointer to the current position in the buffer,
* corresponding to the arguments on stack
* 'end' - pointer to the end of the registers argument
* buffer.
* Note that we are handling integer arguments and floating-point arguments
* identically, depending on which register area is passed to this function.
*
* 'reg_args' - pointer to the current position in the buffer,
* corresponding to the register arguments.
* 'reg_args_end' - pointer to the end of the registers argument
* buffer.
* 'stack_args' - pointer to the current position in the buffer,
* corresponding to the arguments on stack.
* 'data' - typed data to put on the stack.
*/
static inline void alloc_word(uint64_t* &ireg_args,
uint64_t* &stack_args,
uint64_t* end,
uint64_t data)
template<typename T>
static inline void alloc_arg(uint64_t* &reg_args,
uint64_t* reg_args_end,
uint64_t* &stack_args,
T* data)
{
if (ireg_args < end) {
*ireg_args = data;
ireg_args++;
if (reg_args < reg_args_end) {
memcpy(reg_args, data, sizeof(T));
reg_args++;
} else {
*stack_args = data;
memcpy(stack_args, data, sizeof(T));
// Allocate a word-sized stack slot no matter what.
stack_args++;
}
}
static inline void alloc_double(double* &freg_args,
uint64_t* &stack_args,
double* end,
double data)
{
if (freg_args < end) {
*freg_args = data;
freg_args++;
} else {
memcpy(stack_args, &data, sizeof(data));
stack_args++;
}
}
static inline void alloc_float(double* &freg_args,
uint64_t* &stack_args,
double* end,
float data)
{
if (freg_args < end) {
memcpy(freg_args, &data, sizeof(data));
freg_args++;
} else {
memcpy(stack_args, &data, sizeof(data));
stack_args++;
}
}
extern "C" void
invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
uint32_t paramCount, nsXPTCVariant* s)
{
uint64_t *ireg_args = stk;
uint64_t *ireg_end = ireg_args + 8;
double *freg_args = (double *)ireg_end;
double *freg_end = freg_args + 8;
uint64_t *stack_args = (uint64_t *)freg_end;
// Pun on integer and floating-point registers being the same size.
uint64_t *freg_args = ireg_end;
uint64_t *freg_end = freg_args + 8;
uint64_t *stack_args = freg_end;
// leave room for 'that' argument in x0
++ireg_args;
@ -102,10 +80,10 @@ invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
// slots.
switch (s->type) {
case nsXPTType::T_FLOAT:
alloc_float(freg_args, stack_args, freg_end, s->val.f);
alloc_arg(freg_args, freg_end, stack_args, &s->val.f);
continue;
case nsXPTType::T_DOUBLE:
alloc_double(freg_args, stack_args, freg_end, s->val.d);
alloc_arg(freg_args, freg_end, stack_args, &s->val.d);
continue;
case nsXPTType::T_I8: word = s->val.i8; break;
case nsXPTType::T_I16: word = s->val.i16; break;
@ -125,7 +103,7 @@ invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
}
}
alloc_word(ireg_args, stack_args, ireg_end, word);
alloc_arg(ireg_args, ireg_end, stack_args, &word);
}
}