Line 0
Link Here
|
|
|
1 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 |
/* ***** BEGIN LICENSE BLOCK ***** |
3 |
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
4 |
* |
5 |
* The contents of this file are subject to the Mozilla Public License Version |
6 |
* 1.1 (the "License"); you may not use this file except in compliance with |
7 |
* the License. You may obtain a copy of the License at |
8 |
* http://www.mozilla.org/MPL/ |
9 |
* |
10 |
* Software distributed under the License is distributed on an "AS IS" basis, |
11 |
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
12 |
* for the specific language governing rights and limitations under the |
13 |
* License. |
14 |
* |
15 |
* The Original Code is mozilla.org code. |
16 |
* |
17 |
* The Initial Developer of the Original Code is |
18 |
* Netscape Communications Corporation. |
19 |
* Portions created by the Initial Developer are Copyright (C) 1999 |
20 |
* the Initial Developer. All Rights Reserved. |
21 |
* |
22 |
* Contributor(s): |
23 |
* dwmw2@infradead.org (David Woodhouse) |
24 |
* Franz.Sirl-kernel@lauterbach.com (Franz Sirl) |
25 |
* beard@netscape.com (Patrick Beard) |
26 |
* waterson@netscape.com (Chris Waterson) |
27 |
* |
28 |
* Alternatively, the contents of this file may be used under the terms of |
29 |
* either of the GNU General Public License Version 2 or later (the "GPL"), |
30 |
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
31 |
* in which case the provisions of the GPL or the LGPL are applicable instead |
32 |
* of those above. If you wish to allow use of your version of this file only |
33 |
* under the terms of either the GPL or the LGPL, and not to allow others to |
34 |
* use your version of this file under the terms of the MPL, indicate your |
35 |
* decision by deleting the provisions above and replace them with the notice |
36 |
* and other provisions required by the GPL or the LGPL. If you do not delete |
37 |
* the provisions above, a recipient may use your version of this file under |
38 |
* the terms of any one of the MPL, the GPL or the LGPL. |
39 |
* |
40 |
* ***** END LICENSE BLOCK ***** */ |
41 |
|
42 |
// Implement shared vtbl methods. |
43 |
|
44 |
#include "xptcprivate.h" |
45 |
|
46 |
// The Linux/PPC ABI (aka PPC/SYSV ABI) passes the first 8 integral |
47 |
// parameters and the first 13 floating point parameters in registers |
48 |
// (r3-r10 and f1-f13), no stack space is allocated for these by the |
49 |
// caller. The rest of the parameters are passed in the callers stack |
50 |
// area. The stack pointer has to retain 16-byte alignment, longlongs |
51 |
// and doubles are aligned on 8-byte boundaries. |
52 |
|
53 |
#define PARAM_BUFFER_COUNT 16 |
54 |
#define GPR_COUNT 7 |
55 |
#define FPR_COUNT 13 |
56 |
|
57 |
// PrepareAndDispatch() is called by SharedStub() and calls the actual method. |
58 |
// |
59 |
// - 'args[]' contains the arguments passed on stack |
60 |
// - 'gprData[]' contains the arguments passed in integer registers |
61 |
// - 'fprData[]' contains the arguments passed in floating point registers |
62 |
// |
63 |
// The parameters are mapped into an array of type 'nsXPTCMiniVariant' |
64 |
// and then the method gets called. |
65 |
#include <stdio.h> |
66 |
extern "C" nsresult |
67 |
PrepareAndDispatch(nsXPTCStubBase* self, |
68 |
PRUint64 methodIndex, |
69 |
PRUint64* args, |
70 |
PRUint64 *gprData, |
71 |
double *fprData) |
72 |
{ |
73 |
nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT]; |
74 |
nsXPTCMiniVariant* dispatchParams = NULL; |
75 |
nsIInterfaceInfo* iface_info = NULL; |
76 |
const nsXPTMethodInfo* info; |
77 |
PRUint32 paramCount; |
78 |
PRUint32 i; |
79 |
nsresult result = NS_ERROR_FAILURE; |
80 |
|
81 |
NS_ASSERTION(self,"no self"); |
82 |
|
83 |
self->GetInterfaceInfo(&iface_info); |
84 |
NS_ASSERTION(iface_info,"no interface info"); |
85 |
if (! iface_info) |
86 |
return NS_ERROR_UNEXPECTED; |
87 |
|
88 |
iface_info->GetMethodInfo(PRUint16(methodIndex), &info); |
89 |
NS_ASSERTION(info,"no method info"); |
90 |
if (! info) |
91 |
return NS_ERROR_UNEXPECTED; |
92 |
|
93 |
paramCount = info->GetParamCount(); |
94 |
|
95 |
// setup variant array pointer |
96 |
if(paramCount > PARAM_BUFFER_COUNT) |
97 |
dispatchParams = new nsXPTCMiniVariant[paramCount]; |
98 |
else |
99 |
dispatchParams = paramBuffer; |
100 |
|
101 |
NS_ASSERTION(dispatchParams,"no place for params"); |
102 |
if (! dispatchParams) |
103 |
return NS_ERROR_OUT_OF_MEMORY; |
104 |
|
105 |
PRUint64* ap = args; |
106 |
PRUint64 tempu64; |
107 |
|
108 |
for(i = 0; i < paramCount; i++) { |
109 |
const nsXPTParamInfo& param = info->GetParam(i); |
110 |
const nsXPTType& type = param.GetType(); |
111 |
nsXPTCMiniVariant* dp = &dispatchParams[i]; |
112 |
|
113 |
if (!param.IsOut() && type == nsXPTType::T_DOUBLE) { |
114 |
if (i < FPR_COUNT) |
115 |
dp->val.d = fprData[i]; |
116 |
else |
117 |
dp->val.d = *(double*) ap; |
118 |
} else if (!param.IsOut() && type == nsXPTType::T_FLOAT) { |
119 |
if (i < FPR_COUNT) |
120 |
dp->val.f = (float) fprData[i]; // in registers floats are passed as doubles |
121 |
else { |
122 |
float *p = (float *)ap; |
123 |
p++; |
124 |
dp->val.f = *p; |
125 |
} |
126 |
} else { /* integer type or pointer */ |
127 |
if (i < GPR_COUNT) |
128 |
tempu64 = gprData[i]; |
129 |
else |
130 |
tempu64 = *ap; |
131 |
|
132 |
if (param.IsOut() || !type.IsArithmetic()) |
133 |
dp->val.p = (void*) tempu64; |
134 |
else if (type ==nsXPTType::T_I8) |
135 |
dp->val.i8 = (PRInt8) tempu64; |
136 |
else if (type ==nsXPTType::T_I16) |
137 |
dp->val.i16 = (PRInt16) tempu64; |
138 |
else if (type ==nsXPTType::T_I32) |
139 |
dp->val.i32 = (PRInt32) tempu64; |
140 |
else if (type ==nsXPTType::T_I64) |
141 |
dp->val.i64 = (PRInt64) tempu64; |
142 |
else if (type ==nsXPTType::T_U8) |
143 |
dp->val.u8 = (PRUint8) tempu64; |
144 |
else if (type ==nsXPTType::T_U16) |
145 |
dp->val.u16 = (PRUint16) tempu64; |
146 |
else if (type ==nsXPTType::T_U32) |
147 |
dp->val.u32 = (PRUint32) tempu64; |
148 |
else if (type ==nsXPTType::T_U64) |
149 |
dp->val.u64 = (PRUint64) tempu64; |
150 |
else if (type ==nsXPTType::T_BOOL) |
151 |
dp->val.b = (PRBool) tempu64; |
152 |
else if (type ==nsXPTType::T_CHAR) |
153 |
dp->val.c = (char) tempu64; |
154 |
else if (type ==nsXPTType::T_WCHAR) |
155 |
dp->val.wc = (wchar_t) tempu64; |
156 |
else |
157 |
NS_ASSERTION(0, "bad type"); |
158 |
} |
159 |
|
160 |
if (i >= 7) |
161 |
ap++; |
162 |
} |
163 |
|
164 |
result = self->CallMethod((PRUint16) methodIndex, info, dispatchParams); |
165 |
|
166 |
NS_RELEASE(iface_info); |
167 |
|
168 |
if (dispatchParams != paramBuffer) |
169 |
delete [] dispatchParams; |
170 |
|
171 |
return result; |
172 |
} |
173 |
|
174 |
// Load r11 with the constant 'n' and branch to SharedStub(). |
175 |
// |
176 |
// XXX Yes, it's ugly that we're relying on gcc's name-mangling here; |
177 |
// however, it's quick, dirty, and'll break when the ABI changes on |
178 |
// us, which is what we want ;-). |
179 |
|
180 |
#if __GXX_ABI_VERSION < 100 |
181 |
#error Prehistoric GCC not supported here |
182 |
#else |
183 |
// gcc-3 version |
184 |
// |
185 |
// As G++3 ABI contains the length of the functionname in the mangled |
186 |
// name, it is difficult to get a generic assembler mechanism like |
187 |
// in the G++ 2.95 case. |
188 |
// Create names would be like: |
189 |
// _ZN14nsXPTCStubBase5Stub1Ev |
190 |
// _ZN14nsXPTCStubBase6Stub12Ev |
191 |
// _ZN14nsXPTCStubBase7Stub123Ev |
192 |
// _ZN14nsXPTCStubBase8Stub1234Ev |
193 |
// etc. |
194 |
// Use assembler directives to get the names right... |
195 |
|
196 |
# define STUB_ENTRY(n) \ |
197 |
__asm__ ( \ |
198 |
".section \".toc\",\"aw\" \n\t" \ |
199 |
".section \".text\" \n\t" \ |
200 |
".align 2 \n\t" \ |
201 |
".if "#n" < 10 \n\t" \ |
202 |
".globl _ZN14nsXPTCStubBase5Stub"#n"Ev \n\t" \ |
203 |
".section \".opd\",\"aw\" \n\t" \ |
204 |
".align 3 \n\t" \ |
205 |
"_ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ |
206 |
".quad ._ZN14nsXPTCStubBase5Stub"#n"Ev,.TOC.@tocbase \n\t" \ |
207 |
".previous \n\t" \ |
208 |
".type _ZN14nsXPTCStubBase5Stub"#n"Ev,@function \n\n" \ |
209 |
"._ZN14nsXPTCStubBase5Stub"#n"Ev: \n\t" \ |
210 |
\ |
211 |
".elseif "#n" < 100 \n\t" \ |
212 |
".globl _ZN14nsXPTCStubBase6Stub"#n"Ev \n\t" \ |
213 |
".section \".opd\",\"aw\" \n\t" \ |
214 |
".align 3 \n\t" \ |
215 |
"_ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ |
216 |
".quad ._ZN14nsXPTCStubBase6Stub"#n"Ev,.TOC.@tocbase \n\t" \ |
217 |
".previous \n\t" \ |
218 |
".type _ZN14nsXPTCStubBase6Stub"#n"Ev,@function \n\n" \ |
219 |
"._ZN14nsXPTCStubBase6Stub"#n"Ev: \n\t" \ |
220 |
\ |
221 |
".elseif "#n" < 1000 \n\t" \ |
222 |
".globl _ZN14nsXPTCStubBase7Stub"#n"Ev \n\t" \ |
223 |
".section \".opd\",\"aw\" \n\t" \ |
224 |
".align 3 \n\t" \ |
225 |
"_ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ |
226 |
".quad ._ZN14nsXPTCStubBase7Stub"#n"Ev,.TOC.@tocbase \n\t" \ |
227 |
".previous \n\t" \ |
228 |
".type _ZN14nsXPTCStubBase7Stub"#n"Ev,@function \n\n" \ |
229 |
"._ZN14nsXPTCStubBase7Stub"#n"Ev: \n\t" \ |
230 |
\ |
231 |
".else \n\t" \ |
232 |
".err \"stub number "#n" >= 1000 not yet supported\"\n" \ |
233 |
".endif \n\t" \ |
234 |
\ |
235 |
"li 11,"#n" \n\t" \ |
236 |
"b SharedStub \n" \ |
237 |
); |
238 |
#endif |
239 |
|
240 |
#define SENTINEL_ENTRY(n) \ |
241 |
nsresult nsXPTCStubBase::Sentinel##n() \ |
242 |
{ \ |
243 |
NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \ |
244 |
return NS_ERROR_NOT_IMPLEMENTED; \ |
245 |
} |
246 |
|
247 |
#include "xptcstubsdef.inc" |