Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* Platform specific code to invoke XPCOM methods on native objects */
8 #include "xptcprivate.h"
10 #if !defined(__aarch64__)
11 #error "This code is for Linux AArch64 only."
12 #endif
15 /* "Procedure Call Standard for the ARM 64-bit Architecture" document, sections
16 * "5.4 Parameter Passing" and "6.1.2 Procedure Calling" contain all the
17 * needed information.
18 *
19 * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
20 */
22 #ifndef __AARCH64EL__
23 #error "Only little endian compatibility was tested"
24 #endif
26 /*
27 * Allocation of integer function arguments initially to registers r1-r7
28 * and then to stack. Handling of 'that' argument which goes to register r0
29 * is handled separately and does not belong here.
30 *
31 * 'ireg_args' - pointer to the current position in the buffer,
32 * corresponding to the register arguments
33 * 'stack_args' - pointer to the current position in the buffer,
34 * corresponding to the arguments on stack
35 * 'end' - pointer to the end of the registers argument
36 * buffer.
37 */
38 static inline void alloc_word(uint64_t* &ireg_args,
39 uint64_t* &stack_args,
40 uint64_t* end,
41 uint64_t data)
42 {
43 if (ireg_args < end) {
44 *ireg_args = data;
45 ireg_args++;
46 } else {
47 *stack_args = data;
48 stack_args++;
49 }
50 }
52 static inline void alloc_double(double* &freg_args,
53 uint64_t* &stack_args,
54 double* end,
55 double data)
56 {
57 if (freg_args < end) {
58 *freg_args = data;
59 freg_args++;
60 } else {
61 memcpy(stack_args, &data, sizeof(data));
62 stack_args++;
63 }
64 }
66 static inline void alloc_float(double* &freg_args,
67 uint64_t* &stack_args,
68 double* end,
69 float data)
70 {
71 if (freg_args < end) {
72 memcpy(freg_args, &data, sizeof(data));
73 freg_args++;
74 } else {
75 memcpy(stack_args, &data, sizeof(data));
76 stack_args++;
77 }
78 }
81 extern "C" void
82 invoke_copy_to_stack(uint64_t* stk, uint64_t *end,
83 uint32_t paramCount, nsXPTCVariant* s)
84 {
85 uint64_t *ireg_args = stk;
86 uint64_t *ireg_end = ireg_args + 8;
87 double *freg_args = (double *)ireg_end;
88 double *freg_end = freg_args + 8;
89 uint64_t *stack_args = (uint64_t *)freg_end;
91 // leave room for 'that' argument in x0
92 ++ireg_args;
94 for (uint32_t i = 0; i < paramCount; i++, s++) {
95 if (s->IsPtrData()) {
96 alloc_word(ireg_args, stack_args, ireg_end, (uint64_t)s->ptr);
97 continue;
98 }
99 // According to the ABI, integral types that are smaller than 8 bytes
100 // are to be passed in 8-byte registers or 8-byte stack slots.
101 switch (s->type) {
102 case nsXPTType::T_FLOAT:
103 alloc_float(freg_args, stack_args, freg_end, s->val.f);
104 break;
105 case nsXPTType::T_DOUBLE:
106 alloc_double(freg_args, stack_args, freg_end, s->val.d);
107 break;
108 case nsXPTType::T_I8: alloc_word(ireg_args, stk, end, s->val.i8); break;
109 case nsXPTType::T_I16: alloc_word(ireg_args, stk, end, s->val.i16); break;
110 case nsXPTType::T_I32: alloc_word(ireg_args, stk, end, s->val.i32); break;
111 case nsXPTType::T_I64: alloc_word(ireg_args, stk, end, s->val.i64); break;
112 case nsXPTType::T_U8: alloc_word(ireg_args, stk, end, s->val.u8); break;
113 case nsXPTType::T_U16: alloc_word(ireg_args, stk, end, s->val.u16); break;
114 case nsXPTType::T_U32: alloc_word(ireg_args, stk, end, s->val.u32); break;
115 case nsXPTType::T_U64: alloc_word(ireg_args, stk, end, s->val.u64); break;
116 case nsXPTType::T_BOOL: alloc_word(ireg_args, stk, end, s->val.b); break;
117 case nsXPTType::T_CHAR: alloc_word(ireg_args, stk, end, s->val.c); break;
118 case nsXPTType::T_WCHAR: alloc_word(ireg_args, stk, end, s->val.wc); break;
119 default:
120 // all the others are plain pointer types
121 alloc_word(ireg_args, stack_args, ireg_end,
122 reinterpret_cast<uint64_t>(s->val.p));
123 break;
124 }
125 }
126 }
128 extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
129 uint32_t paramCount, nsXPTCVariant* params);
131 EXPORT_XPCOM_API(nsresult)
132 NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
133 uint32_t paramCount, nsXPTCVariant* params)
134 {
135 return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
136 }