xpcom/reflect/xptcall/src/md/win32/xptcstubs_x86_64_gnu.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "xptcprivate.h"
michael@0 8 #include "xptiprivate.h"
michael@0 9
michael@0 10 /*
michael@0 11 * This is for Windows 64 bit (x86_64) using GCC syntax
michael@0 12 * Code was copied from the MSVC version.
michael@0 13 */
michael@0 14
michael@0 15 #if !defined(_AMD64_) || !defined(__GNUC__)
michael@0 16 # error xptcstubs_x86_64_gnu.cpp being used unexpectedly
michael@0 17 #endif
michael@0 18
michael@0 19 extern "C" nsresult __attribute__((__used__))
michael@0 20 PrepareAndDispatch(nsXPTCStubBase * self, uint32_t methodIndex,
michael@0 21 uint64_t * args, uint64_t * gprData, double *fprData)
michael@0 22 {
michael@0 23 #define PARAM_BUFFER_COUNT 16
michael@0 24 //
michael@0 25 // "this" pointer is first parameter, so parameter count is 3.
michael@0 26 //
michael@0 27 #define PARAM_GPR_COUNT 3
michael@0 28 #define PARAM_FPR_COUNT 3
michael@0 29
michael@0 30 nsXPTCMiniVariant paramBuffer[PARAM_BUFFER_COUNT];
michael@0 31 nsXPTCMiniVariant* dispatchParams = nullptr;
michael@0 32 const nsXPTMethodInfo* info = nullptr;
michael@0 33 uint8_t paramCount;
michael@0 34 uint8_t i;
michael@0 35 nsresult result = NS_ERROR_FAILURE;
michael@0 36
michael@0 37 NS_ASSERTION(self, "no self");
michael@0 38
michael@0 39 self->mEntry->GetMethodInfo(uint16_t(methodIndex), &info);
michael@0 40 NS_ASSERTION(info, "no method info");
michael@0 41
michael@0 42 paramCount = info->GetParamCount();
michael@0 43
michael@0 44 //
michael@0 45 // setup variant array pointer
michael@0 46 //
michael@0 47
michael@0 48 if(paramCount > PARAM_BUFFER_COUNT)
michael@0 49 dispatchParams = new nsXPTCMiniVariant[paramCount];
michael@0 50 else
michael@0 51 dispatchParams = paramBuffer;
michael@0 52
michael@0 53 NS_ASSERTION(dispatchParams,"no place for params");
michael@0 54
michael@0 55 uint64_t* ap = args;
michael@0 56 uint32_t iCount = 0;
michael@0 57
michael@0 58 for(i = 0; i < paramCount; i++)
michael@0 59 {
michael@0 60 const nsXPTParamInfo& param = info->GetParam(i);
michael@0 61 const nsXPTType& type = param.GetType();
michael@0 62 nsXPTCMiniVariant* dp = &dispatchParams[i];
michael@0 63
michael@0 64 if(param.IsOut() || !type.IsArithmetic())
michael@0 65 {
michael@0 66 if (iCount < PARAM_GPR_COUNT)
michael@0 67 dp->val.p = (void*)gprData[iCount++];
michael@0 68 else
michael@0 69 dp->val.p = (void*)*ap++;
michael@0 70
michael@0 71 continue;
michael@0 72 }
michael@0 73 // else
michael@0 74 switch(type)
michael@0 75 {
michael@0 76 case nsXPTType::T_I8:
michael@0 77 if (iCount < PARAM_GPR_COUNT)
michael@0 78 dp->val.i8 = (int8_t)gprData[iCount++];
michael@0 79 else
michael@0 80 dp->val.i8 = *((int8_t*)ap++);
michael@0 81 break;
michael@0 82
michael@0 83 case nsXPTType::T_I16:
michael@0 84 if (iCount < PARAM_GPR_COUNT)
michael@0 85 dp->val.i16 = (int16_t)gprData[iCount++];
michael@0 86 else
michael@0 87 dp->val.i16 = *((int16_t*)ap++);
michael@0 88 break;
michael@0 89
michael@0 90 case nsXPTType::T_I32:
michael@0 91 if (iCount < PARAM_GPR_COUNT)
michael@0 92 dp->val.i32 = (int32_t)gprData[iCount++];
michael@0 93 else
michael@0 94 dp->val.i32 = *((int32_t*)ap++);
michael@0 95 break;
michael@0 96
michael@0 97 case nsXPTType::T_I64:
michael@0 98 if (iCount < PARAM_GPR_COUNT)
michael@0 99 dp->val.i64 = (int64_t)gprData[iCount++];
michael@0 100 else
michael@0 101 dp->val.i64 = *((int64_t*)ap++);
michael@0 102 break;
michael@0 103
michael@0 104 case nsXPTType::T_U8:
michael@0 105 if (iCount < PARAM_GPR_COUNT)
michael@0 106 dp->val.u8 = (uint8_t)gprData[iCount++];
michael@0 107 else
michael@0 108 dp->val.u8 = *((uint8_t*)ap++);
michael@0 109 break;
michael@0 110
michael@0 111 case nsXPTType::T_U16:
michael@0 112 if (iCount < PARAM_GPR_COUNT)
michael@0 113 dp->val.u16 = (uint16_t)gprData[iCount++];
michael@0 114 else
michael@0 115 dp->val.u16 = *((uint16_t*)ap++);
michael@0 116 break;
michael@0 117
michael@0 118 case nsXPTType::T_U32:
michael@0 119 if (iCount < PARAM_GPR_COUNT)
michael@0 120 dp->val.u32 = (uint32_t)gprData[iCount++];
michael@0 121 else
michael@0 122 dp->val.u32 = *((uint32_t*)ap++);
michael@0 123 break;
michael@0 124
michael@0 125 case nsXPTType::T_U64:
michael@0 126 if (iCount < PARAM_GPR_COUNT)
michael@0 127 dp->val.u64 = (uint64_t)gprData[iCount++];
michael@0 128 else
michael@0 129 dp->val.u64 = *((uint64_t*)ap++);
michael@0 130 break;
michael@0 131
michael@0 132 case nsXPTType::T_FLOAT:
michael@0 133 if (iCount < PARAM_FPR_COUNT)
michael@0 134 dp->val.f = (float)fprData[iCount++];
michael@0 135 else
michael@0 136 dp->val.f = *((float*)ap++);
michael@0 137 break;
michael@0 138
michael@0 139 case nsXPTType::T_DOUBLE:
michael@0 140 if (iCount < PARAM_FPR_COUNT)
michael@0 141 dp->val.d = (double)fprData[iCount++];
michael@0 142 else
michael@0 143 dp->val.d = *((double*)ap++);
michael@0 144 break;
michael@0 145
michael@0 146 case nsXPTType::T_BOOL:
michael@0 147 if (iCount < PARAM_GPR_COUNT)
michael@0 148 dp->val.b = (bool)gprData[iCount++];
michael@0 149 else
michael@0 150 dp->val.b = *((bool*)ap++);
michael@0 151 break;
michael@0 152
michael@0 153 case nsXPTType::T_CHAR:
michael@0 154 if (iCount < PARAM_GPR_COUNT)
michael@0 155 dp->val.c = (char)gprData[iCount++];
michael@0 156 else
michael@0 157 dp->val.c = *((char*)ap++);
michael@0 158 break;
michael@0 159
michael@0 160 case nsXPTType::T_WCHAR:
michael@0 161 if (iCount < PARAM_GPR_COUNT)
michael@0 162 dp->val.wc = (wchar_t)gprData[iCount++];
michael@0 163 else
michael@0 164 dp->val.wc = *((wchar_t*)ap++);
michael@0 165 break;
michael@0 166
michael@0 167 default:
michael@0 168 NS_ASSERTION(0, "bad type");
michael@0 169 break;
michael@0 170 }
michael@0 171 }
michael@0 172
michael@0 173 result = self->mOuter->CallMethod((uint16_t)methodIndex, info, dispatchParams);
michael@0 174
michael@0 175 if(dispatchParams != paramBuffer)
michael@0 176 delete [] dispatchParams;
michael@0 177
michael@0 178 return result;
michael@0 179 }
michael@0 180
michael@0 181 __asm__ (
michael@0 182 ".text\n"
michael@0 183 ".intel_syntax noprefix\n" /* switch to Intel syntax to look like the MSVC assembly */
michael@0 184 ".globl SharedStub\n"
michael@0 185 ".def SharedStub ; .scl 3 ; .type 46 ; .endef \n"
michael@0 186 "SharedStub:\n"
michael@0 187 "sub rsp, 104\n"
michael@0 188
michael@0 189 /* rcx is this pointer. Need backup for optimized build */
michael@0 190
michael@0 191 "mov qword ptr [rsp+88], rcx\n"
michael@0 192
michael@0 193 /*
michael@0 194 * fist 4 parameters (1st is "this" pointer) are passed in registers.
michael@0 195 */
michael@0 196
michael@0 197 /* for floating value */
michael@0 198
michael@0 199 "movsd qword ptr [rsp+64], xmm1\n"
michael@0 200 "movsd qword ptr [rsp+72], xmm2\n"
michael@0 201 "movsd qword ptr [rsp+80], xmm3\n"
michael@0 202
michael@0 203 /* for integer value */
michael@0 204
michael@0 205 "mov qword ptr [rsp+40], rdx\n"
michael@0 206 "mov qword ptr [rsp+48], r8\n"
michael@0 207 "mov qword ptr [rsp+56], r9\n"
michael@0 208
michael@0 209 /*
michael@0 210 * Call PrepareAndDispatch function
michael@0 211 */
michael@0 212
michael@0 213 /* 5th parameter (floating parameters) of PrepareAndDispatch */
michael@0 214
michael@0 215 "lea r9, qword ptr [rsp+64]\n"
michael@0 216 "mov qword ptr [rsp+32], r9\n"
michael@0 217
michael@0 218 /* 4th parameter (normal parameters) of PrepareAndDispatch */
michael@0 219
michael@0 220 "lea r9, qword ptr [rsp+40]\n"
michael@0 221
michael@0 222 /* 3rd parameter (pointer to args on stack) */
michael@0 223
michael@0 224 "lea r8, qword ptr [rsp+40+104]\n"
michael@0 225
michael@0 226 /* 2nd parameter (vtbl_index) */
michael@0 227
michael@0 228 "mov rdx, r11\n"
michael@0 229
michael@0 230 /* 1st parameter (this) (rcx) */
michael@0 231
michael@0 232 "call PrepareAndDispatch\n"
michael@0 233
michael@0 234 /* restore rcx */
michael@0 235
michael@0 236 "mov rcx, qword ptr [rsp+88]\n"
michael@0 237
michael@0 238 /*
michael@0 239 * clean up register
michael@0 240 */
michael@0 241
michael@0 242 "add rsp, 104+8\n"
michael@0 243
michael@0 244 /* set return address */
michael@0 245
michael@0 246 "mov rdx, qword ptr [rsp-8]\n"
michael@0 247
michael@0 248 /* simulate __stdcall return */
michael@0 249
michael@0 250 "jmp rdx\n"
michael@0 251
michael@0 252 /* back to AT&T syntax */
michael@0 253 ".att_syntax\n"
michael@0 254 );
michael@0 255
michael@0 256 #define STUB_ENTRY(n) \
michael@0 257 asm(".intel_syntax noprefix\n" /* this is in intel syntax */ \
michael@0 258 ".text\n" \
michael@0 259 ".align 2\n" \
michael@0 260 ".if " #n " < 10\n" \
michael@0 261 ".globl _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \
michael@0 262 ".def _ZN14nsXPTCStubBase5Stub" #n "Ev@4\n" \
michael@0 263 ".scl 3\n" /* private */ \
michael@0 264 ".type 46\n" /* function returning unsigned int */ \
michael@0 265 ".endef\n" \
michael@0 266 "_ZN14nsXPTCStubBase5Stub" #n "Ev@4:\n" \
michael@0 267 ".elseif " #n " < 100\n" \
michael@0 268 ".globl _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \
michael@0 269 ".def _ZN14nsXPTCStubBase6Stub" #n "Ev@4\n" \
michael@0 270 ".scl 3\n" /* private */\
michael@0 271 ".type 46\n" /* function returning unsigned int */ \
michael@0 272 ".endef\n" \
michael@0 273 "_ZN14nsXPTCStubBase6Stub" #n "Ev@4:\n" \
michael@0 274 ".elseif " #n " < 1000\n" \
michael@0 275 ".globl _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \
michael@0 276 ".def _ZN14nsXPTCStubBase7Stub" #n "Ev@4\n" \
michael@0 277 ".scl 3\n" /* private */ \
michael@0 278 ".type 46\n" /* function returning unsigned int */ \
michael@0 279 ".endef\n" \
michael@0 280 "_ZN14nsXPTCStubBase7Stub" #n "Ev@4:\n" \
michael@0 281 ".else\n" \
michael@0 282 ".err \"stub number " #n " >= 1000 not yet supported\"\n" \
michael@0 283 ".endif\n" \
michael@0 284 "mov r11, " #n "\n" \
michael@0 285 "jmp SharedStub\n" \
michael@0 286 ".att_syntax\n" /* back to AT&T syntax */ \
michael@0 287 "");
michael@0 288
michael@0 289 #define SENTINEL_ENTRY(n) \
michael@0 290 nsresult nsXPTCStubBase::Sentinel##n() \
michael@0 291 { \
michael@0 292 NS_ASSERTION(0,"nsXPTCStubBase::Sentinel called"); \
michael@0 293 return NS_ERROR_NOT_IMPLEMENTED; \
michael@0 294 }
michael@0 295
michael@0 296 #include "xptcstubsdef.inc"
michael@0 297

mercurial