summaryrefslogtreecommitdiff
path: root/bridges/source/cpp_uno/msvc_win32_x86-64
diff options
context:
space:
mode:
authorTor Lillqvist <tlillqvist@novell.com>2011-01-27 15:44:09 +0200
committerTor Lillqvist <tlillqvist@novell.com>2011-01-27 23:39:59 +0200
commitdc433642ab86c55ab1184521f9e7259bed57dab5 (patch)
treea5b9e9cd1a04d8b20a45e3f12a96e58fdd2532b5 /bridges/source/cpp_uno/msvc_win32_x86-64
parent5e8635f624406d63988ff55006ceed4cb705e80e (diff)
More work on the x64 Windows C++-UNO bridge
Diffstat (limited to 'bridges/source/cpp_uno/msvc_win32_x86-64')
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm328
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm186
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx542
-rw-r--r--bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk11
4 files changed, 463 insertions, 604 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm
deleted file mode 100644
index 09f1177b9a9e..000000000000
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/asmbits.asm
+++ /dev/null
@@ -1,328 +0,0 @@
-; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 32; comment-start: "; " comment-start-skip: "; *" -*-
-
-;*************************************************************************
-;*
-;* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-;*
-;* Copyright 2000, 2011 Oracle and/or its affiliates.
-;*
-;* OpenOffice.org - a multi-platform office productivity suite
-;*
-;* This file is part of OpenOffice.org.
-;*
-;* OpenOffice.org is free software: you can redistribute it and/or modify
-;* it under the terms of the GNU Lesser General Public License version 3
-;* only, as published by the Free Software Foundation.
-;*
-;* OpenOffice.org is distributed in the hope that it will be useful,
-;* but WITHOUT ANY WARRANTY; without even the implied warranty of
-;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;* GNU Lesser General Public License version 3 for more details
-;* (a copy is included in the LICENSE file that accompanied this code).
-;*
-;* You should have received a copy of the GNU Lesser General Public License
-;* version 3 along with OpenOffice.org. If not, see
-;* <http://www.openoffice.org/license.html>
-;* for a copy of the LGPLv3 License.
-;*
-;************************************************************************
-
-; Emacs asm-mode is not really ideal for the convention in this
-; file. So I use text-mode with custom comment syntax... not really
-; ideal either. Maybe I should just re-format this to match asm-mode's
-; conventions?
-
-; NOTE: EXTREMELY UNFINISHED, I KNOW. WORK IN PROGRESS.
-
-; I really don't have a good high-level understanding of the big
-; picture and what the actual task of the C++/UNO bridge is yet... I
-; should debug the x86 version and see what is actually going on to
-; get an understanding.
-
-; This is in a separate file for x86-64 as MSVC doesn't have in-line
-; assembly for x64. The code here is still partly just a crude copy of
-; the in-line x86 code from ../msvc_win32_intel that is totally
-; pointless on x64. But parts have been properly changed into x64
-; calling convention and might even work.
-
-; Random web links and other documentation about low-level
-; implementation details for the C++/UNO bridge on x64 Windows kept
-; here:
-
-; Caolan's "Lazy Hackers Guide To Porting" is useful:
-; http://wiki.services.openoffice.org/wiki/Lazy_Hackers_Guide_To_Porting
-
-; As for details about the x64 Windows calling convention, register
-; usage, stack usage, exception handling etc, the official
-; documentation (?) on MSDN is a bit fragmented and split up into a
-; needlessly large number of short pages. But still:
-; http://msdn.microsoft.com/en-us/library/7kcdt6fy%28v=VS.90%29.aspx
-
-; Also see Raymond Chen's blog post:
-; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx
-
-; This one is actually more readable: "Improving Automated Analysis of
-; Windows x64 Binaries":
-; http://www.uninformed.org/?v=4&a=1
-
-; The bridge uses dynamic code generation. For exception handling and
-; unwinding to work across that (as I assume we want?), one apparently
-; needs to use either RtlAddFunctionTable() or
-; RtlInstallFunctionTableCallback(). See Windows SDK documentation.
-
-; Random interesting discussion threads:
-; http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/300bd6d3-9381-4d2d-8129-e48b392c05d8
-
-; Ken Johnson's blog http://www.nynaeve.net/ has much interesting
-; information, for instance:
-; http://www.nynaeve.net/?p=11
-
-; From <typelib/typeclass.h>
-typelib_TypeClass_VOID = 0
-typelib_TypeClass_CHAR = 1
-typelib_TypeClass_BOOLEAN = 2
-typelib_TypeClass_BYTE = 3
-typelib_TypeClass_SHORT = 4
-typelib_TypeClass_UNSIGNED_SHORT = 5
-typelib_TypeClass_LONG = 6
-typelib_TypeClass_UNSIGNED_LONG = 7
-typelib_TypeClass_HYPER = 8
-typelib_TypeClass_UNSIGNED_HYPER = 9
-typelib_TypeClass_FLOAT = 10
-typelib_TypeClass_DOUBLE = 11
-typelib_TypeClass_ENUM = 15
-
-extrn __copyConstruct : proc
-extrn __destruct : proc
-extrn cpp_mediate: proc
-
-.code
-
-; First we have three code snippets that aren't real functions, but
-; "naked" (in x86 calling convention parlance) functions jumped to
-; from code generated in C++.
-
-; I think that for x64 Windows we shouldn't be jumping so wildly from
-; generated code snippets into fixed code snippets here. "Procedures"
-; should be continuous in memory, or the unwinding information will be
-; broken. (For dynamically generated code, that is dynamically
-; registered unwind information, obviously.)
-
-; So instead of generating jumps into here, we should just make the
-; C++ code copy the machine code that these three "naked" functions
-; compile to after the snippet it is generating. Of course, that means
-; the code here needs to be position independent, or (eek) that we
-; would need to come up with some home-brewed minimal relocation
-; mechanism.
-
-; Jumped to from code generated in except.cxx: ObjectFunction::ObjectFunction()
-
-copyConstruct proc
- ; ObjectFunction this already on stack
- push [rsp+8] ; source exc object this
- push rcx ; exc object
- call __copyConstruct
- add rsp, 12 ; + ObjectFunction this
- ret 4
-copyConstruct endp
-
-; Ditto
-
-destruct proc
- ; ObjectFunction this already on stack
- push rcx ; exc object
- call __destruct
- add rsp, 8 ; + ObjectFunction this
- ret
-destruct endp
-
-; Jumped to from code generated in cpp2uno.cxx:codeSnippet()
-
-cpp_vtable_call proc
- sub rsp, 8 ; space for immediate return type
- push rsp
- push rdx ; vtable offset
- push rax ; function index
- mov rax, rsp
- add rax, 20
- push rax ; original stack ptr
-
- call cpp_mediate
- add rsp, 16
-
- cmp rax, typelib_TypeClass_FLOAT
- je Lfloat
- cmp rax, typelib_TypeClass_DOUBLE
- je Ldouble
- cmp rax, typelib_TypeClass_HYPER
- je Lhyper
- cmp eax, typelib_TypeClass_UNSIGNED_HYPER
- je Lhyper
- ; rest is eax
- pop rax
- add rsp, 4
- ret
-Lhyper:
- pop rax
- pop rdx
- ret
-Lfloat:
- fld dword ptr [rsp]
- add rsp, 8
- ret
-Ldouble:
- fld qword ptr [rsp]
- add rsp, 8
- ret
-cpp_vtable_call endp
-
-; Called from uno2cpp.cxx
-
-; This one is now hopefully proper x64 Windows code following the
-; appropriate conventions and might actually work.
-
-; void callVirtualMethod( ; location on entry
-; void * pAdjustedThisPtr, ; rcx
-; sal_Int32 nVtableIndex, ; rdx
-; void * pReturn, ; r8
-; typelib_TypeClass eReturnTypeClass, ; r9
-; sal_Int64 * pStack, ; ((4+1)*8)[rsp]
-; sal_Int32 nStack ; ((5+1)*8)[rsp]
-; sal_uInt64 *pGPR, ; ((6+1)*8)[rsp]
-; double *pFPR) ; ((7+1)*8)[rsp]
-
-callVirtualMethod proc frame
- ; Prologue
- mov ((3+1)*8)[rsp], r9
- mov ((2+1)*8)[rsp], r8
- mov ((0+1)*8)[rsp], rcx
- push rsi
- .pushreg rsi
- push rdi
- .pushreg rdi
-
- ; Our stack frame size is 24 qwords (space for 20 parameters
- ; to pass, plus the two pushed registers rsi and rdi, plus
- ; return address, rounded up to 16 bytes)
-
- sub rsp, (20+1)*8
- .allocstack (20+1)*8
- .endprolog
-
- ; Stack parameters first
-
- ; nStack is number of qwords of stack space (including spilled
- ; registers). If four or less, 4 is passed in anyway to make
- ; code here simpler.
-
- mov rcx, ((24+5)*8)[rsp] ; nStack
- sub rcx, 4
- jle Lxmmregs
-
- mov rsi, ((24+4)*8)[rsp] ; pStack
- add rsi, 32
- lea rdi, 32[rsp]
- rep movsq
-
-Lxmmregs:
- ; Parameters passed in XMM registers
-
- ; We don't bother checking which actually needed, if any.
- mov rax, ((24+7)*8)[rsp] ; pFPR
- movsd xmm0, qword ptr [rax]
- movsd xmm1, qword ptr 8[rax]
- movsd xmm2, qword ptr 16[rax]
- movsd xmm3, qword ptr 24[rax]
-
- ; Prepare pointer to function to call
- mov rcx, ((24+0)*8)[rsp]
- mov r12, [rcx] ; pAdjustedThisPtr->vtable
- shl rdx, 3 ; nVtableIndex *= 8
- add r12, rdx
-
- ; Fill parameters passed in general purpose registers
- mov rax, ((24+6)*8)[rsp] ; pGPR
- mov rcx, (0*8)[rax]
- mov rdx, (1*8)[rax]
- mov r8, (2*8)[rax]
- mov r9, (3*8)[rax]
-
- call qword ptr [r12]
-
- ; Test return type
- mov r9, ((24+3)*8)[rsp]
- cmp r9, typelib_TypeClass_VOID
- je Lepilog
-
- ; int32
- cmp r9, typelib_TypeClass_LONG
- je Lint32
- cmp r9, typelib_TypeClass_UNSIGNED_LONG
- je Lint32
- cmp r9, typelib_TypeClass_ENUM
- je Lint32
-
- ; int8
- cmp r9, typelib_TypeClass_BOOLEAN
- je Lint8
- cmp r9, typelib_TypeClass_BYTE
- je Lint8
-
- ; int16
- cmp r9, typelib_TypeClass_CHAR
- je Lint16
- cmp r9, typelib_TypeClass_SHORT
- je Lint16
- cmp r9, typelib_TypeClass_UNSIGNED_SHORT
- je Lint16
-
- ; int64
- cmp r9, typelib_TypeClass_HYPER
- je Lint64
- cmp r9, typelib_TypeClass_UNSIGNED_HYPER
- je Lint64
-
- ; float
- cmp r9, typelib_TypeClass_FLOAT
- je Lfloat
-
- ; double
- cmp r9, typelib_TypeClass_DOUBLE
- je Ldouble
-
- jmp Lepilog ; no simple type
-
-Lint8:
- mov byte ptr [r8], al
- jmp Lepilog
-
-Lint16:
- mov word ptr [r8], ax
- jmp Lepilog
-
-Lint32:
- mov dword ptr [r8], eax
- jmp Lepilog
-
-Lint64:
- mov qword ptr [r8], rax
- jmp Lepilog
-
-Lfloat:
- movss dword ptr [r8], xmm0
- jmp Lepilog
-
-Ldouble:
- movsd qword ptr [r8], xmm0
-
-Lepilog:
- ; Epilogue
- add rsp, (20+1)*8
- pop rdi
- pop rsi
- ret
-callVirtualMethod endp
-
-end
-
-; vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm
new file mode 100644
index 000000000000..30322d350411
--- /dev/null
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm
@@ -0,0 +1,186 @@
+; -*- Mode: text; tab-width: 8; indent-tabs-mode: nil comment-column: 44; comment-start: ";; " comment-start-skip: ";; *" -*-
+
+;; Version: MPL 1.1 / GPLv3+ / LGPLv3+
+;;
+;; The contents of this file are subject to the Mozilla Public License Version
+;; 1.1 (the "License"); you may not use this file except in compliance with
+;; the License or as specified alternatively below. You may obtain a copy of
+;; the License at http://www.mozilla.org/MPL/
+;;
+;; Software distributed under the License is distributed on an "AS IS" basis,
+;; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+;; for the specific language governing rights and limitations under the
+;; License.
+;;
+;; The Initial Developer of the Original Code is
+;; Novell, Inc.
+;; Portions created by the Initial Developer are Copyright (C) 2011 the
+;; Initial Developer. All Rights Reserved.
+;;
+;; Major Contributor(s):
+;; Tor Lillqvist <tml@iki.fi>
+;; Portions created by Tor Lillqvist are Copyright (C) 2011 Tor Lillqvist. All Rights Reserved.
+;;
+;; For minor contributions see the git repository.
+;;
+;; Alternatively, the contents of this file may be used under the terms of
+;; either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+;; the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+;; in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+;; instead of those above.
+
+;; This is the template source code for the trampoline generated by
+;; codeSnippet() in cpp2uno.cxx. codeSnippet() copies the code from
+;; this function, modifying it as necessary in a few places. The
+;; generated trampoline calls cpp_vtable_call() which then calls the
+;; actual UNO function.
+
+;; We keep this as a separate .asm file here so that it is easy to
+;; modify, and we don't need to laborously enter machine code into
+;; codeSnippet().
+
+;; This is in a separate file for x86-64 as MSVC doesn't have in-line
+;; assembly for x64. The code here is still partly just a crude copy of
+;; the in-line x86 code from ../msvc_win32_intel that is totally
+;; pointless on x64. But parts have been properly changed into x64
+;; calling convention and might even work.
+
+;; Random web links and other documentation about low-level
+;; implementation details for the C++/UNO bridge on x64 Windows kept
+;; here:
+
+;; Caolan's "Lazy Hackers Guide To Porting" is useful:
+;; http://wiki.services.openoffice.org/wiki/Lazy_Hackers_Guide_To_Porting
+
+;; As for details about the x64 Windows calling convention, register
+;; usage, stack usage, exception handling etc, the official
+;; documentation (?) on MSDN is a bit fragmented and split up into a
+;; needlessly large number of short pages. But still:
+;; http://msdn.microsoft.com/en-us/library/7kcdt6fy%28v=VS.90%29.aspx
+
+;; Also see Raymond Chen's blog post:
+;; http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx
+
+;; This one is actually more readable: "Improving Automated Analysis
+;; of Windows x64 Binaries": http://www.uninformed.org/?v=4&a=1
+
+;; For exception handling and unwinding to work across the generated
+;; functions (as I assume we want?), we would need call
+;; RtlAddFunctionTable() (and RtlDeleteFunctionTable()). See Windows
+;; SDK documentation.
+
+;; Random interesting discussion threads:
+;; http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/300bd6d3-9381-4d2d-8129-e48b392c05d8
+
+;; Ken Johnson's blog http://www.nynaeve.net/ has much interesting
+;; information, for instance:
+;; http://www.nynaeve.net/?p=11
+
+;; The code snippet generated is called from "normal" C++ code which
+;; has no idea that it is calling dynamically generated code.
+
+typelib_TypeClass_FLOAT equ 10
+typelib_TypeClass_DOUBLE equ 11
+
+extern cpp_vtable_call: proc
+
+.code
+
+;; Single instruction templates. For each register paramter, which can
+;; be either in an integer or floating-point register, either of two
+;; instruction sequences are used, either:
+;; mov qword ptr offset[rsp], reg
+;; nop
+;; or:
+;; movsd qwort ptr offset[rsp], xmmreg
+;;
+;; The nop in the integer case is so that both are of equal length
+
+fp_spill_templates:
+public fp_spill_templates
+ movsd qword ptr 32[rsp], xmm3
+ movsd qword ptr 24[rsp], xmm2
+ movsd qword ptr 16[rsp], xmm1
+ movsd qword ptr 8[rsp], xmm0
+fp_spill_templates_end:
+public fp_spill_templates_end
+
+;; The actual template function code here
+
+trampoline_template proc
+
+ ;; Spill our register parameters. In the x64 Windows calling
+ ;; convention the caller always has stack space allocated
+ ;; where the callee can spill register parameters.
+
+ ;; The default is integer moves, that are replaced in the
+ ;; generated code snippet with floating-point moves for
+ ;; floating-point parameters.
+
+ mov qword ptr 32[rsp], r9
+ nop
+ mov qword ptr 24[rsp], r8
+ nop
+ mov qword ptr 16[rsp], rdx
+ nop
+ mov qword ptr 8[rsp], rcx
+ nop
+trampoline_template_spill_end::
+public trampoline_template_spill_end
+
+ ;; Make stack frame. Re-align RSP at 16 bytes. We need just one
+ ;; qword of stack for our own purposes: Where cpp_vtable_call()
+ ;; will store the return value of the UNO callee. But we of course
+ ;; must also allocate space for the functions we call (i.e., just
+ ;; cpp_vtable_call()) to spill their register parameters.
+
+ sub rsp, 40
+
+ ;; Call cpp_vtable_call() with 3 parameters:
+
+ ;; 1 (rcx): nFunctionIndex
+ ;; 2 (rdx): nVtableOffset
+ ;; 3 (r8): pointer to where to store return value, followed by our
+ ;; return address (uninteresting to cpp_vtable_call()), followed
+ ;; by our spilled register parameters, as stored above, followed
+ ;; by the rest of our parameters, if any.
+
+ mov rcx, 12345467890abcdeh ;; nFunctionIndex, actual value generated from
+ ;; parameter to codeSnippet()
+trampoline_template_function_index::
+public trampoline_template_function_index
+
+ mov rdx, 12345467890abcdeh ;; nVtableOffset, ditto
+trampoline_template_vtable_offset::
+public trampoline_template_vtable_offset
+
+ lea r8, 32[rsp] ;; Where cpp_vtable_call() will store the return value
+
+ call cpp_vtable_call ;; Actual address generated by codeSnippet()
+
+ ;; cpp_vtable_call() returns the typelib_TypeClass type of the
+ ;; return value of the called UNO function
+
+ cmp rax, typelib_TypeClass_FLOAT
+ je Lfloat
+
+ cmp rax, typelib_TypeClass_DOUBLE
+ je Lfloat
+
+ mov rax, qword ptr 32[rsp]
+ jmp Lepilogue
+
+Lfloat:
+ movsd xmm0, qword ptr 32[rsp]
+
+Lepilogue:
+ add rsp, 40
+ ret
+trampoline_template_end::
+public trampoline_template_end
+
+trampoline_template endp
+
+end
+
+; vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
index a2310cbd8d7d..29545337b16b 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx
@@ -42,191 +42,180 @@
#include "mscx.hxx"
-using namespace ::com::sun::star::uno;
+// #define DEBUG_WITH_JUST_MESSAGEBOXES
-namespace
-{
+using namespace ::com::sun::star::uno;
//==================================================================================================
static inline typelib_TypeClass cpp2uno_call(
bridges::cpp_uno::shared::CppInterfaceProxy * pThis,
const typelib_TypeDescription * pMemberTypeDescr,
- typelib_TypeDescriptionReference * pReturnTypeRef, // 0 indicates void return
+ typelib_TypeDescriptionReference * pReturnTypeRef, // NULL indicates void return
sal_Int32 nParams, typelib_MethodParameter * pParams,
- void ** pCallStack,
- sal_Int64 * pRegisterReturn /* space for register return */ )
+ void ** pStack )
{
- // pCallStack: ret, this, [complex return ptr], params
- char * pCppStack = (char *)(pCallStack +2);
-
- // return
- typelib_TypeDescription * pReturnTypeDescr = 0;
- if (pReturnTypeRef)
- {
+ // Return type
+ typelib_TypeDescription * pReturnTypeDescr = NULL;
+ if ( pReturnTypeRef )
TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
- }
- void * pUnoReturn = 0;
- void * pCppReturn = 0; // complex return ptr: if != 0 && != pUnoReturn, reconversion need
+ int nFirstRealParam = 2;
- if (pReturnTypeDescr)
+ void * pUnoReturn = NULL;
+ void * pCppReturn = NULL; // Complex return ptr: if != NULL && != pUnoReturn, reconversion need
+
+ if ( pReturnTypeDescr )
{
- if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
+ if ( !bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ) )
{
- pUnoReturn = pRegisterReturn; // direct way for simple types
+ pCppReturn = pStack[nFirstRealParam++];
+
+ pUnoReturn = ( bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
+ ? alloca( pReturnTypeDescr->nSize )
+ : pCppReturn ); // direct way
}
- else // complex return via ptr (pCppReturn)
+ else // complex return, store it directly where the C++ called wants it
{
- pCppReturn = *(void **)pCppStack;
- pCppStack += sizeof(void *);
-
- pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
- pReturnTypeDescr )
- ? alloca( pReturnTypeDescr->nSize )
- : pCppReturn); // direct way
+ pUnoReturn = pStack;
}
}
- // parameters
- void ** pUnoArgs = (void **)alloca( 4 * sizeof(void *) * nParams );
- void ** pCppArgs = pUnoArgs + nParams;
- // indexes of values this have to be converted (interface conversion cpp<=>uno)
- sal_Int64 * pTempIndexes = (sal_Int64 *)(pUnoArgs + (2 * nParams));
- // type descriptions for reconversions
- typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pUnoArgs + (3 * nParams));
+ void ** pCppIncomingParams = pStack + nFirstRealParam;
+
+ // Unlike this method for other archs, prefer clarity to
+ // micro-optimization, and allocate these array separately
+
+ // Parameters passed to the UNO function
+ void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams );
- sal_Int32 nTempIndexes = 0;
+ // Parameters received from C++
+ void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
- for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+ // Indexes of values this have to be converted (interface conversion cpp<=>uno)
+ int * pTempIndexes =
+ (int *)alloca( sizeof(int) * nParams );
+
+ // Type descriptions for reconversions
+ typelib_TypeDescription ** ppTempParamTypeDescr =
+ (typelib_TypeDescription **)alloca( sizeof(void *) * nParams );
+
+ int nTempIndexes = 0;
+
+ for ( int nPos = 0; nPos < nParams; ++nPos )
{
const typelib_MethodParameter & rParam = pParams[nPos];
- typelib_TypeDescription * pParamTypeDescr = 0;
- TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
- if (!rParam.bOut
- && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
- // value
+ if ( !rParam.bOut
+ && bridges::cpp_uno::shared::isSimpleType( rParam.pTypeRef ) )
{
- pCppArgs[nPos] = pCppStack;
- pUnoArgs[nPos] = pCppStack;
- switch (pParamTypeDescr->eTypeClass)
- {
- case typelib_TypeClass_HYPER:
- case typelib_TypeClass_UNSIGNED_HYPER:
- case typelib_TypeClass_DOUBLE:
- pCppStack += sizeof(sal_Int64); // extra qword
- break;
- default:
- break;
- }
- // no longer needed
- TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+ pCppArgs[nPos] = pUnoArgs[nPos] = pCppIncomingParams++;
}
else // ptr to complex value | ref
{
- pCppArgs[nPos] = *(void **)pCppStack;
+ typelib_TypeDescription * pParamTypeDescr = 0;
+ TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
- if (! rParam.bIn) // is pure out
+ void * pCppStack;
+
+ pCppArgs[nPos] = pCppStack = *pCppIncomingParams++;
+
+ if ( !rParam.bIn ) // Pure out
{
- // uno out is unconstructed mem!
+ // UNO out is unconstructed mem
pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
pTempIndexes[nTempIndexes] = nPos;
- // will be released at reconversion
+ // pParamTypeDescr will be released at reconversion
ppTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr;
}
- // is in/inout
- else if (bridges::cpp_uno::shared::relatesToInterfaceType(
- pParamTypeDescr ))
+ //
+ else if ( bridges::cpp_uno::shared::relatesToInterfaceType(
+ pParamTypeDescr ) )
{
::uno_copyAndConvertData(
pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize ),
- *(void **)pCppStack, pParamTypeDescr,
+ pCppStack, pParamTypeDescr,
pThis->getBridge()->getCpp2Uno() );
- pTempIndexes[nTempIndexes] = nPos; // has to be reconverted
- // will be released at reconversion
+ pTempIndexes[nTempIndexes] = nPos; // Has to be reconverted
+ // pParamTypeDescr will be released at reconversion
ppTempParamTypeDescr[nTempIndexes++] = pParamTypeDescr;
}
else // direct way
{
- pUnoArgs[nPos] = *(void **)pCppStack;
- // no longer needed
+ pUnoArgs[nPos] = pCppStack;
+ // No longer needed
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
}
- pCppStack += sizeof(sal_Int64); // standard parameter length
}
// ExceptionHolder
uno_Any aUnoExc; // Any will be constructed by callee
uno_Any * pUnoExc = &aUnoExc;
- // invoke uno dispatch call
+ // invoke UNO dispatch call
(*pThis->getUnoI()->pDispatcher)(
pThis->getUnoI(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
// in case an exception occurred...
- if (pUnoExc)
+ if ( pUnoExc )
{
- // destruct temporary in/inout params
- while (nTempIndexes--)
+ // Destruct temporary in/inout params
+ while ( nTempIndexes-- )
{
- sal_Int32 nIndex = pTempIndexes[nTempIndexes];
+ int nIndex = pTempIndexes[nTempIndexes];
- if (pParams[nIndex].bIn) // is in/inout => was constructed
+ if ( pParams[nIndex].bIn ) // Is in/inout => was constructed
{
::uno_destructData( pUnoArgs[nIndex], ppTempParamTypeDescr[nTempIndexes], 0 );
}
TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndexes] );
}
- if (pReturnTypeDescr)
- {
+ if ( pReturnTypeDescr )
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
- }
CPPU_CURRENT_NAMESPACE::mscx_raiseException(
- &aUnoExc, pThis->getBridge()->getUno2Cpp() );
- // has to destruct the any
- // is here for dummy
+ &aUnoExc, pThis->getBridge()->getUno2Cpp() ); // Has to destruct the any
+
+ // Is here for dummy
return typelib_TypeClass_VOID;
}
- else // else no exception occurred...
+ else // Else, no exception occurred...
{
- // temporary params
+ // Temporary params
while (nTempIndexes--)
{
- sal_Int32 nIndex = pTempIndexes[nTempIndexes];
+ int nIndex = pTempIndexes[nTempIndexes];
typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndexes];
- if (pParams[nIndex].bOut) // inout/out
+ if ( pParams[nIndex].bOut ) // inout/out
{
- // convert and assign
+ // Convert and assign
::uno_destructData(
pCppArgs[nIndex], pParamTypeDescr, cpp_release );
::uno_copyAndConvertData(
pCppArgs[nIndex], pUnoArgs[nIndex], pParamTypeDescr,
pThis->getBridge()->getUno2Cpp() );
}
- // destroy temp uno param
+ // Destroy temp uno param
::uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
TYPELIB_DANGER_RELEASE( pParamTypeDescr );
}
- // return
- if (pCppReturn) // has complex return
+ // Return
+ if ( pCppReturn ) // Has complex return
{
- if (pUnoReturn != pCppReturn) // needs reconversion
+ if ( pUnoReturn != pCppReturn ) // Needs reconversion
{
::uno_copyAndConvertData(
pCppReturn, pUnoReturn, pReturnTypeDescr,
pThis->getBridge()->getUno2Cpp() );
- // destroy temp uno return
- ::uno_destructData(
- pUnoReturn, pReturnTypeDescr, 0 );
+ // Destroy temp uno return
+ ::uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
}
- // complex return ptr is set to eax
- *(void **)pRegisterReturn = pCppReturn;
+ // Complex return ptr is set to eax
+ pStack[0] = pCppReturn;
}
- if (pReturnTypeDescr)
+ if ( pReturnTypeDescr )
{
typelib_TypeClass eRet = (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
@@ -238,199 +227,204 @@ static inline typelib_TypeClass cpp2uno_call(
}
//==================================================================================================
-typelib_TypeClass __cdecl cpp_mediate(
- void ** pCallStack, sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
- sal_Int64 * pRegisterReturn /* space for register return */ )
+extern "C" typelib_TypeClass cpp_vtable_call(
+ sal_Int32 nFunctionIndex,
+ sal_Int32 nVtableOffset,
+ void ** pStack )
{
- // pCallStack: ret adr, this, [ret *], params
- void * pThis = static_cast< char * >(pCallStack[1]) - nVtableOffset;
- bridges::cpp_uno::shared::CppInterfaceProxy * pCppI
- = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
- pThis);
+ // pStack points to space for return value, after which
+ // follows our return address (uninteresting) then the spilled
+ // integer or floating-point register parameters from the call to
+ // the trampoline, followed by stack parameters. Note that if the
+ // callee returns a large value, the first parameter is actually a
+ // pointer to where it should store its return value. The first
+ // "real" parameter is the "this" pointer.
+
+ void * pThis;
+ if ( nFunctionIndex & 0x80000000 )
+ {
+ nFunctionIndex &= 0x7fffffff;
+ pThis = pStack[3];
+ }
+ else
+ {
+ pThis = pStack[2];
+ }
+ pThis = static_cast<char *>( pThis ) - nVtableOffset;
+
+ bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
+ bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( pThis );
typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
- OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
- "### illegal vtable index!" );
- if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
+
+ OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex, "### illegal vtable index!\n" );
+ if ( nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex )
{
- throw RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!") ),
- (XInterface *)pThis );
+ throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("illegal vtable index!")),
+ reinterpret_cast<XInterface *>( pCppI ) );
}
// determine called method
sal_Int32 nMemberPos = pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
- OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!" );
+ OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### illegal member index!\n" );
TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
typelib_TypeClass eRet;
- switch (aMemberDescr.get()->eTypeClass)
- {
- case typelib_TypeClass_INTERFACE_ATTRIBUTE:
- {
- if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex)
- {
- // is GET method
- eRet = cpp2uno_call(
- pCppI, aMemberDescr.get(),
- ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
- 0, 0, // no params
- pCallStack, pRegisterReturn );
- }
- else
- {
- // is SET method
- typelib_MethodParameter aParam;
- aParam.pTypeRef =
- ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
- aParam.bIn = sal_True;
- aParam.bOut = sal_False;
-
- eRet = cpp2uno_call(
- pCppI, aMemberDescr.get(),
- 0, // indicates void return
- 1, &aParam,
- pCallStack, pRegisterReturn );
- }
- break;
- }
- case typelib_TypeClass_INTERFACE_METHOD:
+ switch ( aMemberDescr.get()->eTypeClass )
{
- // is METHOD
- switch (nFunctionIndex)
+ case typelib_TypeClass_INTERFACE_ATTRIBUTE:
{
- // standard XInterface vtable calls
- case 1: // acquire()
- pCppI->acquireProxy(); // non virtual call!
- eRet = typelib_TypeClass_VOID;
- break;
- case 2: // release()
- pCppI->releaseProxy(); // non virtual call!
- eRet = typelib_TypeClass_VOID;
+ typelib_TypeDescriptionReference *pAttrTypeRef =
+ reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( aMemberDescr.get() )->pAttributeTypeRef;
+
+ if ( pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex )
+ {
+ // is GET method
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(), pAttrTypeRef,
+ 0, NULL, // no params
+ pStack );
+ }
+ else
+ {
+ // is SET method
+ typelib_MethodParameter aParam;
+ aParam.pTypeRef = pAttrTypeRef;
+ aParam.bIn = sal_True;
+ aParam.bOut = sal_False;
+
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+ 0, // indicates void return
+ 1, &aParam,
+ pStack );
+ }
break;
- case 0: // queryInterface() opt
+ }
+ case typelib_TypeClass_INTERFACE_METHOD:
{
- typelib_TypeDescription * pTD = 0;
- TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pCallStack[3] )->getTypeLibType() );
- if (pTD)
+ // is METHOD
+ switch ( nFunctionIndex )
{
- XInterface * pInterface = 0;
- (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
- pCppI->getBridge()->getCppEnv(),
- (void **)&pInterface, pCppI->getOid().pData,
- (typelib_InterfaceTypeDescription *)pTD );
-
- if (pInterface)
- {
- ::uno_any_construct(
- reinterpret_cast< uno_Any * >( pCallStack[2] ),
- &pInterface, pTD, cpp_acquire );
- pInterface->release();
- TYPELIB_DANGER_RELEASE( pTD );
- *(void **)pRegisterReturn = pCallStack[2];
- eRet = typelib_TypeClass_ANY;
+ case 1: // acquire()
+ pCppI->acquireProxy(); // non virtual call!
+ eRet = typelib_TypeClass_VOID;
+ break;
+ case 2: // release()
+ pCppI->releaseProxy(); // non virtual call!
+ eRet = typelib_TypeClass_VOID;
break;
+ case 0: // queryInterface() opt
+ {
+ typelib_TypeDescription * pTD = NULL;
+ // the incoming C++ parameters are: The hidden return value pointer,
+ // the this pointer, and then the actual queryInterface() only parameter.
+ // Thus pStack[4], the third parameter.
+ TYPELIB_DANGER_GET( &pTD, reinterpret_cast<Type *>( pStack[4] )->getTypeLibType() );
+
+ if ( pTD )
+ {
+ XInterface * pInterface = NULL;
+ (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)
+ ( pCppI->getBridge()->getCppEnv(),
+ (void **)&pInterface,
+ pCppI->getOid().pData,
+ reinterpret_cast<typelib_InterfaceTypeDescription *>( pTD ) );
+
+ if ( pInterface )
+ {
+ // pStack[0] = hidden return value pointer
+ ::uno_any_construct( reinterpret_cast<uno_Any *>( pStack[0] ),
+ &pInterface, pTD, cpp_acquire );
+
+ pInterface->release();
+ TYPELIB_DANGER_RELEASE( pTD );
+
+ eRet = typelib_TypeClass_ANY;
+ break;
+ }
+ TYPELIB_DANGER_RELEASE( pTD );
+ }
+ } // Fall through!
+ default:
+ {
+ typelib_InterfaceMethodTypeDescription *pMethodTD =
+ reinterpret_cast<typelib_InterfaceMethodTypeDescription *>( aMemberDescr.get() );
+
+ eRet = cpp2uno_call( pCppI, aMemberDescr.get(),
+ pMethodTD->pReturnTypeRef,
+ pMethodTD->nParams,
+ pMethodTD->pParams,
+ pStack );
}
- TYPELIB_DANGER_RELEASE( pTD );
}
- } // else perform queryInterface()
+ break;
+ }
default:
- eRet = cpp2uno_call(
- pCppI, aMemberDescr.get(),
- ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
- ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
- ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
- pCallStack, pRegisterReturn );
+ {
+ throw RuntimeException( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("no member description found!")),
+ reinterpret_cast<XInterface *>( pCppI ) );
+ // is here for dummy
+ eRet = typelib_TypeClass_VOID;
}
- break;
- }
- default:
- {
- throw RuntimeException(
- rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("no member description found!") ),
- (XInterface *)pThis );
- // is here for dummy
- eRet = typelib_TypeClass_VOID;
- }
}
return eRet;
}
-extern void *cpp_vtable_call;
-
//==================================================================================================
-int const codeSnippetSize = 28;
+extern "C" {
+
+// These are actually addresses in the code compiled from codeSnippet.asm
+extern char
+ fp_spill_templates,
+ fp_spill_templates_end,
+ trampoline_template,
+ trampoline_template_spill_end,
+ trampoline_template_function_index,
+ trampoline_template_vtable_offset,
+ trampoline_template_end;
+}
+
+int const codeSnippetSize = (int) (&trampoline_template_end - &trampoline_template);
// This function generates the code that acts as a proxy for the UNO function to be called.
// The generated code does the following:
// - Save register parametrs.
unsigned char * codeSnippet(
- unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset)
+ unsigned char * code,
+ char param_kind[4],
+ sal_Int32 functionIndex,
+ sal_Int32 vtableOffset,
+ bool bHasHiddenParam )
{
- unsigned char * p = code;
-
- // mov eax, functionIndex:
- *p++ = 0xB8;
- *reinterpret_cast< sal_Int32 * >(p) = functionIndex;
- p += sizeof (sal_Int32);
-
- // mov edx, vtableOffset:
- *p++ = 0xBA;
- *reinterpret_cast< sal_Int32 * >(p) = vtableOffset;
- p += sizeof (sal_Int32);
-
-#if 0
- sub esp, 8 // space for immediate return type
- push esp
- push edx // vtable offset
- push eax // function index
- mov eax, esp
- add eax, 20
- push eax // original stack ptr
-
- call cpp_mediate
- add esp, 16
-
- cmp eax, typelib_TypeClass_FLOAT
- je Lfloat
- cmp eax, typelib_TypeClass_DOUBLE
- je Ldouble
- cmp eax, typelib_TypeClass_HYPER
- je Lhyper
- cmp eax, typelib_TypeClass_UNSIGNED_HYPER
- je Lhyper
- // rest is eax
- pop eax
- add esp, 4
- ret
-Lhyper:
- pop eax
- pop edx
- ret
-Lfloat:
- fld dword ptr [esp]
- add esp, 8
- ret
-Ldouble:
- fld qword ptr [esp]
- add esp, 8
- ret
+ OSL_ASSERT( (&fp_spill_templates_end - &fp_spill_templates) ==
+ (&trampoline_template_spill_end - &trampoline_template) );
-#endif
+ OSL_ASSERT( ((&fp_spill_templates_end - &fp_spill_templates) / 4) * 4 ==
+ (&fp_spill_templates_end - &fp_spill_templates) );
-#if 0
- // jmp rel64 cpp_vtable_call:
- *p++ = 0xE9;
- *reinterpret_cast< sal_Int64 * >(p)
- = ((unsigned char *) cpp_vtable_call) - p - sizeof (sal_Int64);
- p += sizeof (sal_Int64);
-#endif
- OSL_ASSERT(p - code <= codeSnippetSize);
- return code + codeSnippetSize;
-}
+ if ( bHasHiddenParam )
+ functionIndex |= 0x80000000;
+ int const one_spill_instruction_size = (int) ((&fp_spill_templates_end - &fp_spill_templates)) / 4;
+
+ memcpy( code, &trampoline_template, codeSnippetSize );
+
+ for (int i = 0; i < 4; ++i)
+ if ( param_kind[i] == CPPU_CURRENT_NAMESPACE::REGPARAM_FLT )
+ memcpy (code + i*one_spill_instruction_size,
+ &fp_spill_templates + i*one_spill_instruction_size,
+ one_spill_instruction_size);
+
+ ((sal_uInt64*) trampoline_template_function_index)[-1] = functionIndex;
+ ((sal_uInt64*) trampoline_template_vtable_offset)[-1] = vtableOffset;
+
+ // TODO: Add unwind data for the dynamically generated function by
+ // calling RtlAddFunctionTable(). We also need to remove the
+ // unwind data with RtlDeleteFunctionTable() in freeExec() then.
+
+ return code + codeSnippetSize;
}
struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
@@ -468,9 +462,7 @@ bridges::cpp_uno::shared::VtableFactory::initializeBlock(
return slots + slotCount;
}
-#if 0
-
-#else
+#ifdef DEBUG_WITH_JUST_MESSAGEBOXES
static void whatthefuck(sal_Int64 i, ...)
{
@@ -493,28 +485,33 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
TYPELIB_DANGER_GET( &pTD, type->ppMembers[ i ] );
OSL_ASSERT( pTD );
- CPPU_CURRENT_NAMESPACE::RegParamKind param_kind[4];
+ char param_kind[4];
int nr = 0;
+ for (int i = 0; i < 4; ++i)
+ param_kind[i] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT;
+
if ( pTD->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE )
{
typelib_InterfaceAttributeTypeDescription *pAttrTD =
reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( pTD );
- // get method
-#if 0
+ // Getter
+
+#ifndef DEBUG_WITH_JUST_MESSAGEBOXES
(s++)->fn = code;
- code = codeSnippet(code, functionOffset++, vtableOffset);
+ code = codeSnippet( code, param_kind, functionOffset++, vtableOffset,
+ pTD->nSize > 8);
#else
(s++)->fn = whatthefuck;
#endif
if ( ! pAttrTD->bReadOnly )
{
- // set method
-#if 0
+ // Setter
+#ifndef DEBUG_WITH_JUST_MESSAGEBOXES
(s++)->fn = code;
- code = codeSnippet(code, functionOffset++, vtableOffset);
+ code = codeSnippet( code, param_kind, functionOffset++, vtableOffset, false );
#else
(s++)->fn = whatthefuck;
#endif
@@ -529,14 +526,14 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
TYPELIB_DANGER_GET( &pReturnTD, pMethodTD->pReturnTypeRef );
OSL_ASSERT( pReturnTD );
- if ( pReturnTD->nSize > 8 ) {
+ if ( pReturnTD->nSize > 8 )
+ {
// Hidden return value
- param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT;
+ nr++;
}
- TYPELIB_DANGER_RELEASE( pReturnTD );
// 'this'
- param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT;
+ nr++;
for (int j = 0; nr < 4 && j < pMethodTD->nParams; ++j)
{
@@ -548,21 +545,24 @@ unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
if ( pParamTD->eTypeClass == typelib_TypeClass_FLOAT ||
pParamTD->eTypeClass == typelib_TypeClass_DOUBLE )
param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_FLT;
- else
- param_kind[nr++] = CPPU_CURRENT_NAMESPACE::REGPARAM_INT;
TYPELIB_DANGER_RELEASE( pParamTD );
+ }
-#if 0
- (s++)->fn = code;
- code = codeSnippet(code, functionOffset++, vtableOffset);
+#ifndef DEBUG_WITH_JUST_MESSAGEBOXES
+ (s++)->fn = code;
+ code = codeSnippet( code, param_kind, functionOffset++, vtableOffset,
+ pReturnTD->nSize > 8);
#else
- (s++)->fn = whatthefuck;
+ (s++)->fn = whatthefuck;
#endif
- }
+
+ TYPELIB_DANGER_RELEASE( pReturnTD );
}
else
OSL_ASSERT( false );
+
+ TYPELIB_DANGER_RELEASE( pTD );
}
return code;
}
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
index 604799a18e5a..e813fad0c4cc 100644
--- a/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
+++ b/bridges/source/cpp_uno/msvc_win32_x86-64/makefile.mk
@@ -51,10 +51,11 @@ CFLAGS += -DLEAK_STATIC_DATA
SLOFILES= \
- $(SLO)$/cpp2uno.obj \
- $(SLO)$/uno2cpp.obj \
- $(SLO)$/dllinit.obj \
- $(SLO)$/except.obj
+ $(SLO)$/cpp2uno.obj \
+ $(SLO)$/uno2cpp.obj \
+ $(SLO)$/dllinit.obj \
+ $(SLO)$/except.obj \
+ $(SLO)$/codeSnippet.obj
NOOPTFILES= \
$(SLO)$/except.obj
@@ -70,7 +71,7 @@ SHL1OBJS = $(SLOFILES)
SHL1LIBS = $(SLB)$/cpp_uno_shared.lib
SHL1STDLIBS= \
- $(CPPULIB) \
+ $(CPPULIB) \
$(SALLIB)
DEF1NAME=$(SHL1TARGET)