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

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

mercurial