bridges: add a Windows Arm64 UNO bridge
Since Microsoft follows the general ARM64 ABI calling conventions, and the SEH exception handling is the same, this result is a mixed port of the gcc3_linux_aarch64 bridge and the refactored x86-64 exception handling. I have no idea, if the complicated 32-bit handling in RaiseInfo() is needed, as the ARM64 trampolines definitly use 64-bit code. But since this is the first working version, I currently don't mind much ;-) There is definitly more potential for refactoring in the whole bridges directory... Change-Id: I9782a2e99c0231cdd1286af156ad312229eccf39 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103642 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
This commit is contained in:
parent
f11dc8335c
commit
03aacdb73d
@ -557,7 +557,9 @@ $(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_URE,ure, \
|
||||
) \
|
||||
log_uno_uno \
|
||||
unsafe_uno_uno \
|
||||
$(if $(filter MSC,$(COM)),$(if $(filter INTEL,$(CPUNAME)),msci,mscx),gcc3)_uno \
|
||||
$(if $(filter MSC,$(COM)), \
|
||||
$(if $(filter INTEL,$(CPUNAME)),msci, \
|
||||
$(if $(filter ARM64,$(CPUNAME)),msca,mscx)),gcc3)_uno \
|
||||
))
|
||||
|
||||
$(eval $(call gb_Helper_register_libraries_for_install,PRIVATELIBS_URE,ure, \
|
||||
|
@ -21,6 +21,13 @@ $(call gb_LinkTarget_get_target,$(call gb_Library_get_linktarget,gcc3_uno)) : \
|
||||
EXTRAOBJECTLISTS += $(call gb_CustomTarget_get_workdir,bridges/source/cpp_uno/gcc3_linux_arm)/armhelper.objectlist
|
||||
endif
|
||||
|
||||
else ifeq ($(CPUNAME),ARM64)
|
||||
|
||||
bridges_SELECTED_BRIDGE := msvc_win32_arm64
|
||||
bridge_exception_objects := cpp2uno uno2cpp abi
|
||||
bridge_noopt_objects := except
|
||||
bridge_asm_objects := callvirtualfunction vtableslotcall
|
||||
|
||||
else ifeq ($(CPUNAME),AARCH64)
|
||||
|
||||
ifneq ($(filter ANDROID DRAGONFLY FREEBSD LINUX MACOSX NETBSD OPENBSD,$(OS)),)
|
||||
|
59
bridges/inc/msvc/arm64.hxx
Normal file
59
bridges/inc/msvc/arm64.hxx
Normal file
@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <msvc/except.hxx>
|
||||
|
||||
#pragma pack(push, 8)
|
||||
|
||||
struct ExceptionType final
|
||||
{
|
||||
sal_Int32 _n0; // flags
|
||||
sal_uInt32 _pTypeInfo; // typeinfo
|
||||
sal_Int32 _n1, _n2, _n3; // thiscast
|
||||
sal_Int32 _n4; // object_size
|
||||
sal_uInt32 _pCopyCtor; // copyctor
|
||||
ExceptionTypeInfo exc_type_info;
|
||||
|
||||
explicit ExceptionType(unsigned char* pCode, sal_uInt64 pCodeBase,
|
||||
typelib_TypeDescription* pTD) throw();
|
||||
|
||||
ExceptionType(const ExceptionType&) = delete;
|
||||
ExceptionType& operator=(const ExceptionType&) = delete;
|
||||
};
|
||||
|
||||
struct RaiseInfo final
|
||||
{
|
||||
sal_Int32 _n0;
|
||||
sal_uInt32 _pDtor;
|
||||
sal_Int32 _n2;
|
||||
sal_uInt32 _types;
|
||||
|
||||
// Additional fields
|
||||
typelib_TypeDescription* _pTD;
|
||||
unsigned char* _code;
|
||||
sal_uInt64 _codeBase;
|
||||
|
||||
explicit RaiseInfo(typelib_TypeDescription* pTD) throw();
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
@ -38,15 +38,13 @@ constexpr DWORD MSVC_EH_MAGIC_PARAM = 0x19930520;
|
||||
// The NT Exception code that msvcrt uses ('msc' | 0xE0000000)
|
||||
constexpr DWORD MSVC_EH_MAGIC_CODE = 0xE06D7363;
|
||||
|
||||
#ifdef _M_IX86
|
||||
#if defined(_M_IX86)
|
||||
#define MSVC_EH_PARAMETERS 3 // Number of parameters in exception record for x86
|
||||
#else
|
||||
#ifdef _M_AMD64
|
||||
#elif defined(_M_AMD64) || defined(_M_ARM64)
|
||||
#define MSVC_EH_PARAMETERS 4 // Number of parameters in exception record for AMD64
|
||||
#else
|
||||
#error "Unsupported machine type"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class type_info;
|
||||
struct RaiseInfo;
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include <msvc/x86.hxx>
|
||||
#elif defined(_M_AMD64)
|
||||
#include <msvc/amd64.hxx>
|
||||
#elif defined(_M_ARM64)
|
||||
#include <msvc/arm64.hxx>
|
||||
#else
|
||||
#error "Unsupported machine type"
|
||||
#endif
|
||||
@ -137,7 +139,7 @@ ExceptionInfos::~ExceptionInfos() throw()
|
||||
RaiseInfo* ExceptionInfos::getRaiseInfo(typelib_TypeDescription* pTD) throw()
|
||||
{
|
||||
static ExceptionInfos* s_pInfos = []() {
|
||||
#ifdef _M_AMD64
|
||||
#if defined _M_AMD64 || defined _M_ARM64
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo(&systemInfo);
|
||||
allocationGranularity = systemInfo.dwAllocationGranularity;
|
||||
|
158
bridges/source/cpp_uno/msvc_win32_arm64/abi.cxx
Normal file
158
bridges/source/cpp_uno/msvc_win32_arm64/abi.cxx
Normal file
@ -0,0 +1,158 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
#include <sal/types.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "abi.hxx"
|
||||
|
||||
enum StructKind
|
||||
{
|
||||
STRUCT_KIND_EMPTY,
|
||||
STRUCT_KIND_FLOAT,
|
||||
STRUCT_KIND_DOUBLE,
|
||||
STRUCT_KIND_POD,
|
||||
STRUCT_KIND_DTOR
|
||||
};
|
||||
|
||||
static StructKind getStructKind(typelib_CompoundTypeDescription const* type)
|
||||
{
|
||||
StructKind k = type->pBaseTypeDescription == 0 ? STRUCT_KIND_EMPTY
|
||||
: getStructKind(type->pBaseTypeDescription);
|
||||
|
||||
for (sal_Int32 i = 0; i != type->nMembers; ++i)
|
||||
{
|
||||
StructKind k2 = StructKind();
|
||||
switch (type->ppTypeRefs[i]->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
case typelib_TypeClass_SHORT:
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_ENUM:
|
||||
k2 = STRUCT_KIND_POD;
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
k2 = STRUCT_KIND_FLOAT;
|
||||
break;
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
k2 = STRUCT_KIND_DOUBLE;
|
||||
break;
|
||||
case typelib_TypeClass_STRING:
|
||||
case typelib_TypeClass_TYPE:
|
||||
case typelib_TypeClass_ANY:
|
||||
case typelib_TypeClass_SEQUENCE:
|
||||
case typelib_TypeClass_INTERFACE:
|
||||
k2 = STRUCT_KIND_DTOR;
|
||||
break;
|
||||
case typelib_TypeClass_STRUCT:
|
||||
{
|
||||
typelib_TypeDescription* td = 0;
|
||||
TYPELIB_DANGER_GET(&td, type->ppTypeRefs[i]);
|
||||
k2 = getStructKind(reinterpret_cast<typelib_CompoundTypeDescription const*>(td));
|
||||
TYPELIB_DANGER_RELEASE(td);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
switch (k2)
|
||||
{
|
||||
case STRUCT_KIND_EMPTY:
|
||||
// this means an empty sub-object, which nevertheless obtains a byte
|
||||
// of storage (TODO: does it?), so the full object cannot be a
|
||||
// homogeneous collection of float or double
|
||||
case STRUCT_KIND_POD:
|
||||
assert(k != STRUCT_KIND_DTOR);
|
||||
k = STRUCT_KIND_POD;
|
||||
break;
|
||||
case STRUCT_KIND_FLOAT:
|
||||
case STRUCT_KIND_DOUBLE:
|
||||
if (k == STRUCT_KIND_EMPTY)
|
||||
{
|
||||
k = k2;
|
||||
}
|
||||
else if (k != k2)
|
||||
{
|
||||
assert(k != STRUCT_KIND_DTOR);
|
||||
k = STRUCT_KIND_POD;
|
||||
}
|
||||
break;
|
||||
case STRUCT_KIND_DTOR:
|
||||
return STRUCT_KIND_DTOR;
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
ReturnKind getReturnKind(typelib_TypeDescription const* type)
|
||||
{
|
||||
switch (type->eTypeClass)
|
||||
{
|
||||
default:
|
||||
assert(false);
|
||||
[[fallthrough]];
|
||||
case typelib_TypeClass_VOID:
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
case typelib_TypeClass_SHORT:
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_ENUM:
|
||||
assert(type->nSize <= 16);
|
||||
return RETURN_KIND_REG;
|
||||
case typelib_TypeClass_STRING:
|
||||
case typelib_TypeClass_TYPE:
|
||||
case typelib_TypeClass_ANY:
|
||||
case typelib_TypeClass_SEQUENCE:
|
||||
case typelib_TypeClass_INTERFACE:
|
||||
return RETURN_KIND_INDIRECT;
|
||||
case typelib_TypeClass_STRUCT:
|
||||
if (type->nSize > 16)
|
||||
{
|
||||
return RETURN_KIND_INDIRECT;
|
||||
}
|
||||
switch (getStructKind(reinterpret_cast<typelib_CompoundTypeDescription const*>(type)))
|
||||
{
|
||||
case STRUCT_KIND_FLOAT:
|
||||
return RETURN_KIND_HFA_FLOAT;
|
||||
case STRUCT_KIND_DOUBLE:
|
||||
return RETURN_KIND_HFA_DOUBLE;
|
||||
case STRUCT_KIND_DTOR:
|
||||
return RETURN_KIND_INDIRECT;
|
||||
default:
|
||||
return RETURN_KIND_REG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
34
bridges/source/cpp_uno/msvc_win32_arm64/abi.hxx
Normal file
34
bridges/source/cpp_uno/msvc_win32_arm64/abi.hxx
Normal file
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <typelib/typedescription.h>
|
||||
|
||||
enum ReturnKind
|
||||
{
|
||||
RETURN_KIND_REG,
|
||||
RETURN_KIND_HFA_FLOAT,
|
||||
RETURN_KIND_HFA_DOUBLE,
|
||||
RETURN_KIND_INDIRECT
|
||||
};
|
||||
|
||||
ReturnKind getReturnKind(typelib_TypeDescription const* type);
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
@ -0,0 +1,72 @@
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
OPT 2 // disable listing
|
||||
// macros to add unwind information
|
||||
#include "ksarm64.h"
|
||||
OPT 1 // re-enable listing
|
||||
|
||||
EXPORT callVirtualFunction
|
||||
|
||||
TEXTAREA, ALIGN=8
|
||||
|
||||
/*
|
||||
extern void callVirtualFunction
|
||||
|
||||
x0 stack
|
||||
x1 frame
|
||||
x2 function
|
||||
x3 return
|
||||
*/
|
||||
|
||||
NESTED_ENTRY callVirtualFunction_fake
|
||||
|
||||
// for unwind information, Windows has to store fp and lr
|
||||
PROLOG_SAVE_REG_PAIR x29, x30, #-32!
|
||||
|
||||
ALTERNATE_ENTRY callVirtualFunction
|
||||
|
||||
// use a stack frame allocated by our caller
|
||||
stp x29, x30, [x1]
|
||||
mov x29, x1
|
||||
mov sp, x0
|
||||
|
||||
mov x9, x2 // function
|
||||
mov x8, x3 // complex return
|
||||
str x3, [x29, #16] // save rvalue
|
||||
|
||||
// load the core argument passing registers
|
||||
ldp x0, x1, [sp, #0]
|
||||
ldp x2, x3, [sp, #16]
|
||||
ldp x4, x5, [sp, #32]
|
||||
ldp x6, x7, [sp, #48]
|
||||
|
||||
ldp d0, d1, [sp, #64]
|
||||
ldp d2, d3, [sp, #80]
|
||||
ldp d4, d5, [sp, #96]
|
||||
ldp d6, d7, [sp, #112]
|
||||
|
||||
blr x9 // call
|
||||
|
||||
ldr x3, [x29, #16] // reload rvalue
|
||||
|
||||
// partially deconstruct the stack frame
|
||||
mov sp, x29
|
||||
ldp x29, x30, [x29]
|
||||
|
||||
// save the simple return values
|
||||
stp x0, x1, [sp, #0]
|
||||
stp d0, d1, [sp, #64]
|
||||
stp d2, d3, [sp, #80]
|
||||
|
||||
NESTED_END callVirtualFunction_fake
|
||||
|
||||
END
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab */
|
432
bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx
Normal file
432
bridges/source/cpp_uno/msvc_win32_arm64/cpp2uno.cxx
Normal file
@ -0,0 +1,432 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <com/sun/star/uno/XInterface.hpp>
|
||||
#include <com/sun/star/uno/genfunc.hxx>
|
||||
#include <sal/alloca.h>
|
||||
#include <sal/types.h>
|
||||
#include <typelib/typeclass.h>
|
||||
#include <typelib/typedescription.h>
|
||||
#include <typelib/typedescription.hxx>
|
||||
|
||||
#include <bridge.hxx>
|
||||
#include <cppinterfaceproxy.hxx>
|
||||
#include <types.hxx>
|
||||
#include <vtablefactory.hxx>
|
||||
|
||||
#include <msvc/arm64.hxx>
|
||||
|
||||
#include "abi.hxx"
|
||||
|
||||
extern "C" void vtableSlotCall();
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
namespace
|
||||
{
|
||||
void call(bridges::cpp_uno::shared::CppInterfaceProxy* proxy,
|
||||
uno::TypeDescription const& description, typelib_TypeDescriptionReference* returnType,
|
||||
sal_Int32 count, typelib_MethodParameter* parameters, sal_uInt64* gpr, sal_uInt64* fpr,
|
||||
sal_uInt64* stack, void* indirectRet)
|
||||
{
|
||||
typelib_TypeDescription* rtd = 0;
|
||||
if (returnType != 0)
|
||||
TYPELIB_DANGER_GET(&rtd, returnType);
|
||||
|
||||
ReturnKind retKind = rtd == 0 ? RETURN_KIND_REG : getReturnKind(rtd);
|
||||
bool retConv = rtd != 0 && bridges::cpp_uno::shared::relatesToInterfaceType(rtd);
|
||||
|
||||
void* retin = retKind == RETURN_KIND_INDIRECT && !retConv ? indirectRet
|
||||
: rtd == 0 ? 0 : alloca(rtd->nSize);
|
||||
void** args = static_cast<void**>(alloca(count * sizeof(void*)));
|
||||
void** cppArgs = static_cast<void**>(alloca(count * sizeof(void*)));
|
||||
typelib_TypeDescription** argtds
|
||||
= static_cast<typelib_TypeDescription**>(alloca(count * sizeof(typelib_TypeDescription*)));
|
||||
|
||||
sal_Int32 ngpr = 1;
|
||||
sal_Int32 nfpr = 0;
|
||||
sal_Int32 sp = 0;
|
||||
for (sal_Int32 i = 0; i != count; ++i)
|
||||
{
|
||||
if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
|
||||
{
|
||||
switch (parameters[i].pTypeRef->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
case typelib_TypeClass_SHORT:
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_ENUM:
|
||||
args[i] = ngpr == 8 ? stack + sp++ : gpr + ngpr++;
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
args[i] = nfpr == 8 ? stack + sp++ : fpr + nfpr++;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
argtds[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cppArgs[i] = reinterpret_cast<void*>(ngpr == 8 ? stack[sp++] : gpr[ngpr++]);
|
||||
typelib_TypeDescription* ptd = 0;
|
||||
TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
|
||||
if (!parameters[i].bIn)
|
||||
{
|
||||
args[i] = alloca(ptd->nSize);
|
||||
argtds[i] = ptd;
|
||||
}
|
||||
else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd))
|
||||
{
|
||||
args[i] = alloca(ptd->nSize);
|
||||
uno_copyAndConvertData(args[i], cppArgs[i], ptd, proxy->getBridge()->getCpp2Uno());
|
||||
argtds[i] = ptd;
|
||||
}
|
||||
else
|
||||
{
|
||||
args[i] = cppArgs[i];
|
||||
argtds[i] = 0;
|
||||
TYPELIB_DANGER_RELEASE(ptd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uno_Any exc;
|
||||
uno_Any* pexc = &exc;
|
||||
proxy->getUnoI()->pDispatcher(proxy->getUnoI(), description.get(), retin, args, &pexc);
|
||||
if (pexc != 0)
|
||||
{
|
||||
for (sal_Int32 i = 0; i != count; ++i)
|
||||
{
|
||||
if (argtds[i] == 0)
|
||||
continue;
|
||||
if (parameters[i].bIn)
|
||||
uno_destructData(args[i], argtds[i], 0);
|
||||
TYPELIB_DANGER_RELEASE(argtds[i]);
|
||||
}
|
||||
if (rtd != 0)
|
||||
TYPELIB_DANGER_RELEASE(rtd);
|
||||
assert(pexc == &exc);
|
||||
msvc_raiseException(&exc, proxy->getBridge()->getUno2Cpp());
|
||||
}
|
||||
|
||||
for (sal_Int32 i = 0; i != count; ++i)
|
||||
{
|
||||
if (argtds[i] != 0)
|
||||
{
|
||||
if (parameters[i].bOut)
|
||||
{
|
||||
uno_destructData(cppArgs[i], argtds[i],
|
||||
reinterpret_cast<uno_ReleaseFunc>(uno::cpp_release));
|
||||
uno_copyAndConvertData(cppArgs[i], args[i], argtds[i],
|
||||
proxy->getBridge()->getUno2Cpp());
|
||||
}
|
||||
uno_destructData(args[i], argtds[i], 0);
|
||||
TYPELIB_DANGER_RELEASE(argtds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void* retout = 0; // avoid false -Werror=maybe-uninitialized
|
||||
switch (retKind)
|
||||
{
|
||||
case RETURN_KIND_REG:
|
||||
switch (rtd == 0 ? typelib_TypeClass_VOID : rtd->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_VOID:
|
||||
break;
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
case typelib_TypeClass_SHORT:
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_ENUM:
|
||||
std::memcpy(gpr, retin, rtd->nSize);
|
||||
assert(!retConv);
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
std::memcpy(fpr, retin, rtd->nSize);
|
||||
assert(!retConv);
|
||||
break;
|
||||
case typelib_TypeClass_STRUCT:
|
||||
if (retConv)
|
||||
{
|
||||
retout = gpr;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(gpr, retin, rtd->nSize);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case RETURN_KIND_HFA_FLOAT:
|
||||
assert(rtd != 0);
|
||||
switch (rtd->nSize)
|
||||
{
|
||||
case 16:
|
||||
std::memcpy(fpr + 3, static_cast<char*>(retin) + 12, 4);
|
||||
[[fallthrough]];
|
||||
case 12:
|
||||
std::memcpy(fpr + 2, static_cast<char*>(retin) + 8, 4);
|
||||
[[fallthrough]];
|
||||
case 8:
|
||||
std::memcpy(fpr + 1, static_cast<char*>(retin) + 4, 4);
|
||||
[[fallthrough]];
|
||||
case 4:
|
||||
std::memcpy(fpr, retin, 4);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
assert(!retConv);
|
||||
break;
|
||||
case RETURN_KIND_HFA_DOUBLE:
|
||||
assert(rtd != 0);
|
||||
std::memcpy(fpr, retin, rtd->nSize);
|
||||
assert(!retConv);
|
||||
break;
|
||||
case RETURN_KIND_INDIRECT:
|
||||
retout = indirectRet;
|
||||
break;
|
||||
}
|
||||
|
||||
if (retConv)
|
||||
{
|
||||
uno_copyAndConvertData(retout, retin, rtd, proxy->getBridge()->getUno2Cpp());
|
||||
uno_destructData(retin, rtd, 0);
|
||||
}
|
||||
|
||||
if (rtd != 0)
|
||||
TYPELIB_DANGER_RELEASE(rtd);
|
||||
}
|
||||
|
||||
extern "C" void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, sal_uInt64* gpr,
|
||||
sal_uInt64* fpr, sal_uInt64* stack, void* indirectRet)
|
||||
{
|
||||
bridges::cpp_uno::shared::CppInterfaceProxy* proxy
|
||||
= bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
|
||||
reinterpret_cast<char*>(gpr[0]) - vtableOffset);
|
||||
typelib_InterfaceTypeDescription* pInterfaceTD = proxy->getTypeDescr();
|
||||
assert(functionIndex < pInterfaceTD->nMapFunctionIndexToMemberIndex);
|
||||
sal_Int32 nMemberPos = pInterfaceTD->pMapFunctionIndexToMemberIndex[functionIndex];
|
||||
assert(nMemberPos < pInterfaceTD->nAllMembers);
|
||||
uno::TypeDescription aMemberDescr(pInterfaceTD->ppAllMembers[nMemberPos]);
|
||||
|
||||
switch (aMemberDescr.get()->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
||||
{
|
||||
typelib_TypeDescriptionReference* pAttrTypeRef
|
||||
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(aMemberDescr.get())
|
||||
->pAttributeTypeRef;
|
||||
|
||||
if (pInterfaceTD->pMapMemberIndexToFunctionIndex[nMemberPos] == functionIndex)
|
||||
{
|
||||
// Getter:
|
||||
call(proxy, aMemberDescr, pAttrTypeRef, 0, 0, gpr, fpr, stack, indirectRet);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Setter:
|
||||
typelib_MethodParameter param = { 0, pAttrTypeRef, true, false };
|
||||
call(proxy, aMemberDescr, 0, 1, ¶m, gpr, fpr, stack, indirectRet);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case typelib_TypeClass_INTERFACE_METHOD:
|
||||
switch (functionIndex)
|
||||
{
|
||||
case 1:
|
||||
proxy->acquireProxy();
|
||||
break;
|
||||
case 2:
|
||||
proxy->releaseProxy();
|
||||
break;
|
||||
case 0:
|
||||
{
|
||||
typelib_TypeDescription* td = nullptr;
|
||||
TYPELIB_DANGER_GET(&td,
|
||||
(reinterpret_cast<uno::Type*>(gpr[1])->getTypeLibType()));
|
||||
if (td != 0 && td->eTypeClass == typelib_TypeClass_INTERFACE)
|
||||
{
|
||||
uno::XInterface* ifc = nullptr;
|
||||
proxy->getBridge()->getCppEnv()->getRegisteredInterface(
|
||||
proxy->getBridge()->getCppEnv(), reinterpret_cast<void**>(&ifc),
|
||||
proxy->getOid().pData,
|
||||
reinterpret_cast<typelib_InterfaceTypeDescription*>(td));
|
||||
if (ifc != 0)
|
||||
{
|
||||
uno_any_construct(reinterpret_cast<uno_Any*>(indirectRet), &ifc, td,
|
||||
reinterpret_cast<uno_AcquireFunc>(uno::cpp_acquire));
|
||||
ifc->release();
|
||||
TYPELIB_DANGER_RELEASE(td);
|
||||
break;
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE(td);
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
typelib_InterfaceMethodTypeDescription* pMethodTD
|
||||
= reinterpret_cast<typelib_InterfaceMethodTypeDescription*>(
|
||||
aMemberDescr.get());
|
||||
call(proxy, aMemberDescr, pMethodTD->pReturnTypeRef, pMethodTD->nParams,
|
||||
pMethodTD->pParams, gpr, fpr, stack, indirectRet);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t const codeSnippetSize = 8 * 4;
|
||||
|
||||
unsigned char* GenerateVTableSlotTrampoline(unsigned char* code, sal_Int32 functionIndex,
|
||||
sal_Int32 vtableOffset)
|
||||
{
|
||||
// movz x9, <low functionIndex>
|
||||
reinterpret_cast<unsigned int*>(code)[0] = 0xD2800009 | ((functionIndex & 0xFFFF) << 5);
|
||||
// movk x9, <high functionIndex>, LSL #16
|
||||
reinterpret_cast<unsigned int*>(code)[1] = 0xF2A00009 | ((functionIndex >> 16) << 5);
|
||||
// movz x10, <low vtableOffset>
|
||||
reinterpret_cast<unsigned int*>(code)[2] = 0xD280000A | ((vtableOffset & 0xFFFF) << 5);
|
||||
// movk x10, <high vtableOffset>, LSL #16
|
||||
reinterpret_cast<unsigned int*>(code)[3] = 0xF2A0000A | ((vtableOffset >> 16) << 5);
|
||||
// ldr x11, +2*4
|
||||
reinterpret_cast<unsigned int*>(code)[4] = 0x5800004B;
|
||||
// br x11
|
||||
reinterpret_cast<unsigned int*>(code)[5] = 0xD61F0160;
|
||||
reinterpret_cast<void**>(code)[3] = reinterpret_cast<void*>(&vtableSlotCall);
|
||||
return code + codeSnippetSize;
|
||||
}
|
||||
}
|
||||
|
||||
namespace bridges::cpp_uno::shared
|
||||
{
|
||||
struct bridges::cpp_uno::shared::VtableFactory::Slot
|
||||
{
|
||||
void* fn;
|
||||
};
|
||||
|
||||
bridges::cpp_uno::shared::VtableFactory::Slot*
|
||||
bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void* block)
|
||||
{
|
||||
return static_cast<Slot*>(block) + 1;
|
||||
}
|
||||
|
||||
std::size_t bridges::cpp_uno::shared::VtableFactory::getBlockSize(sal_Int32 slotCount)
|
||||
{
|
||||
return (slotCount + 1) * sizeof(Slot) + slotCount * codeSnippetSize;
|
||||
}
|
||||
|
||||
bridges::cpp_uno::shared::VtableFactory::Slot*
|
||||
bridges::cpp_uno::shared::VtableFactory::initializeBlock(void* block, sal_Int32 slotCount,
|
||||
sal_Int32,
|
||||
typelib_InterfaceTypeDescription*)
|
||||
{
|
||||
struct Rtti
|
||||
{
|
||||
sal_Int32 n0, n1, n2;
|
||||
type_info* rtti;
|
||||
Rtti()
|
||||
: n0(0)
|
||||
, n1(0)
|
||||
, n2(0)
|
||||
, rtti(RTTInfos::get("com.sun.star.uno.XInterface"))
|
||||
{
|
||||
}
|
||||
};
|
||||
static Rtti rtti;
|
||||
|
||||
Slot* slots = mapBlockToVtable(block);
|
||||
slots[-1].fn = &rtti;
|
||||
return slots + slotCount;
|
||||
}
|
||||
|
||||
unsigned char* VtableFactory::addLocalFunctions(VtableFactory::Slot** slots, unsigned char* code,
|
||||
typelib_InterfaceTypeDescription const* type,
|
||||
sal_Int32 functionOffset, sal_Int32 functionCount,
|
||||
sal_Int32 vtableOffset)
|
||||
{
|
||||
(*slots) -= functionCount;
|
||||
VtableFactory::Slot* s = *slots;
|
||||
for (sal_Int32 i = 0; i != type->nMembers; ++i)
|
||||
{
|
||||
typelib_TypeDescription* td = nullptr;
|
||||
TYPELIB_DANGER_GET(&td, type->ppMembers[i]);
|
||||
assert(td != 0);
|
||||
switch (td->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
||||
{
|
||||
typelib_InterfaceAttributeTypeDescription* atd
|
||||
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription*>(td);
|
||||
// Getter:
|
||||
(s++)->fn = code;
|
||||
code = GenerateVTableSlotTrampoline(code, functionOffset++, vtableOffset);
|
||||
// Setter:
|
||||
if (!atd->bReadOnly)
|
||||
{
|
||||
(s++)->fn = code;
|
||||
code = GenerateVTableSlotTrampoline(code, functionOffset++, vtableOffset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case typelib_TypeClass_INTERFACE_METHOD:
|
||||
(s++)->fn = code;
|
||||
code = GenerateVTableSlotTrampoline(code, functionOffset++, vtableOffset);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE(td);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
void VtableFactory::flushCode(unsigned char const* begin, unsigned char const* end)
|
||||
{
|
||||
FlushInstructionCache(GetCurrentProcess(), begin, end - begin);
|
||||
}
|
||||
|
||||
} // namespace bridges::cpp_uno::shared
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
234
bridges/source/cpp_uno/msvc_win32_arm64/except.cxx
Normal file
234
bridges/source/cpp_uno/msvc_win32_arm64/except.cxx
Normal file
@ -0,0 +1,234 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <malloc.h>
|
||||
#include <new.h>
|
||||
#include <typeinfo>
|
||||
#include <signal.h>
|
||||
|
||||
#include <rtl/alloc.h>
|
||||
#include <rtl/strbuf.hxx>
|
||||
#include <rtl/ustrbuf.hxx>
|
||||
#include <sal/log.hxx>
|
||||
|
||||
#include <com/sun/star/uno/Any.hxx>
|
||||
#include <msvc/arm64.hxx>
|
||||
#include <except.hxx>
|
||||
|
||||
#pragma pack(push, 8)
|
||||
|
||||
using namespace ::com::sun::star;
|
||||
|
||||
static void* __cdecl copyConstruct(void* pExcThis, void* pSource,
|
||||
typelib_TypeDescription* pTD) noexcept
|
||||
{
|
||||
::uno_copyData(pExcThis, pSource, pTD, uno::cpp_acquire);
|
||||
return pExcThis;
|
||||
}
|
||||
|
||||
static void* __cdecl destruct(void* pExcThis, typelib_TypeDescription* pTD) noexcept
|
||||
{
|
||||
::uno_destructData(pExcThis, pTD, uno::cpp_release);
|
||||
return pExcThis;
|
||||
}
|
||||
|
||||
const int nCodeSnippetSize = 28;
|
||||
|
||||
static void GenerateCopyConstructorTrampoline(unsigned char* target,
|
||||
typelib_TypeDescription* pTD) noexcept
|
||||
{
|
||||
// ldr x2, #12
|
||||
// ldr x3, #20
|
||||
// br x3
|
||||
// pTD
|
||||
// ©Construct
|
||||
static const char code[] = "\x62\x00\x00\x58\x83\x00\x00\x58\x60\x00\x1f\xd6";
|
||||
static_assert(sizeof(code) == 13);
|
||||
static const unsigned int code_size = sizeof(code) - 1;
|
||||
|
||||
memcpy(target, code, code_size);
|
||||
*reinterpret_cast<void**>(target + code_size) = pTD;
|
||||
*reinterpret_cast<void**>(target + code_size + 8) = ©Construct;
|
||||
}
|
||||
|
||||
static void GenerateDestructorTrampoline(unsigned char* target,
|
||||
typelib_TypeDescription* pTD) noexcept
|
||||
{
|
||||
// ldr x1, #12
|
||||
// ldr x2, #20
|
||||
// br x2
|
||||
// pTD
|
||||
// &destruct
|
||||
static const char code[] = "\x61\x00\x00\x58\x82\x00\x00\x58\x40\x00\x1f\xd6";
|
||||
static_assert(sizeof(code) == 13);
|
||||
static const unsigned int code_size = sizeof(code) - 1;
|
||||
|
||||
memcpy(target, code, code_size);
|
||||
*reinterpret_cast<void**>(target + code_size) = pTD;
|
||||
*reinterpret_cast<void**>(target + code_size + 8) = &destruct;
|
||||
}
|
||||
|
||||
ExceptionType::ExceptionType(unsigned char* pCode, sal_uInt64 pCodeBase,
|
||||
typelib_TypeDescription* pTD) noexcept
|
||||
: _n0(0)
|
||||
, _n1(0)
|
||||
, _n2(-1)
|
||||
, _n3(0)
|
||||
, _n4(pTD->nSize)
|
||||
, exc_type_info(nullptr, "")
|
||||
{
|
||||
// As _n0 is always initialized to zero, that means the
|
||||
// hasvirtbase flag (see the ONTL catchabletype struct) is
|
||||
// off, and thus the copyctor is of the ctor_ptr kind.
|
||||
|
||||
int len;
|
||||
type_info* pRTTI = RTTInfos::get(pTD->pTypeName, &len);
|
||||
|
||||
memcpy(static_cast<void*>(&exc_type_info), static_cast<void*>(pRTTI), len);
|
||||
_pTypeInfo = static_cast<sal_uInt32>(reinterpret_cast<sal_uInt64>(&exc_type_info) - pCodeBase);
|
||||
GenerateCopyConstructorTrampoline(pCode, pTD);
|
||||
|
||||
assert(pCodeBase <= reinterpret_cast<sal_uInt64>(pCode)
|
||||
&& (reinterpret_cast<sal_uInt64>(pCode) - pCodeBase < 0x100000000));
|
||||
_pCopyCtor = static_cast<sal_uInt32>(reinterpret_cast<sal_uInt64>(pCode) - pCodeBase);
|
||||
}
|
||||
|
||||
/* Rewrite of 32-Bit-Code to work under 64 Bit:
|
||||
* To use the 32 Bit offset values in the ExceptionType we have to
|
||||
* allocate a single allocation block and use it for all code and date
|
||||
* all offsets inside this area are guaranteed to be in 32 bit address range.
|
||||
* So we have to calc total memory allocation size for D-tor, C-Tors,
|
||||
* ExceptionType and type_info. ExceptionType is allocated via placement new
|
||||
* to locate everything inside our mem block.
|
||||
* There is one caveat: Struct type_info is kept in
|
||||
* a map and was referenced from class ExceptionType. Therefore type_info now
|
||||
* is also member of ExceptionType and can be referenced via 32 bit offset.
|
||||
*/
|
||||
|
||||
RaiseInfo::RaiseInfo(typelib_TypeDescription* pTD) noexcept
|
||||
: _n0(0)
|
||||
, _n2(0)
|
||||
, _pTD(pTD)
|
||||
{
|
||||
typelib_CompoundTypeDescription* pCompTD;
|
||||
|
||||
// Count how many trampolines we need
|
||||
int codeSize = nCodeSnippetSize;
|
||||
|
||||
// Info count
|
||||
int nLen = 0;
|
||||
for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
|
||||
pCompTD = pCompTD->pBaseTypeDescription)
|
||||
{
|
||||
++nLen;
|
||||
codeSize += nCodeSnippetSize;
|
||||
}
|
||||
|
||||
// Array with size (4) and all _pTypeInfo (4*nLen)
|
||||
int typeInfoArraySize = 4 + 4 * nLen;
|
||||
|
||||
// 2.Pass: Get the total needed memory for class ExceptionType
|
||||
// (with embedded type_info) and keep the sizes for each instance
|
||||
// is stored in allocated int array
|
||||
auto exceptionTypeSizeArray = std::make_unique<int[]>(nLen);
|
||||
|
||||
nLen = 0;
|
||||
for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
|
||||
pCompTD = pCompTD->pBaseTypeDescription)
|
||||
{
|
||||
int typeInfoLen;
|
||||
RTTInfos::get(pCompTD->aBase.pTypeName, &typeInfoLen);
|
||||
// Mem has to be on 4-byte Boundary
|
||||
if (typeInfoLen % 4 != 0)
|
||||
{
|
||||
int n = typeInfoLen / 4;
|
||||
n++;
|
||||
typeInfoLen = n * 4;
|
||||
}
|
||||
exceptionTypeSizeArray[nLen++] = typeInfoLen + sizeof(ExceptionType);
|
||||
}
|
||||
|
||||
// Total ExceptionType related mem
|
||||
int excTypeAddLen = 0;
|
||||
for (int i = 0; i < nLen; i++)
|
||||
{
|
||||
excTypeAddLen += exceptionTypeSizeArray[i];
|
||||
}
|
||||
|
||||
// Allocate mem for code and all dynamic data in one chunk to guarantee
|
||||
// 32 bit offsets
|
||||
const int totalSize = codeSize + typeInfoArraySize + excTypeAddLen;
|
||||
unsigned char* pCode = _code = static_cast<unsigned char*>(std::malloc(totalSize));
|
||||
int pCodeOffset = 0;
|
||||
|
||||
// New base of types array, starts after Trampoline D-Tor / C-Tors
|
||||
DWORD* types = reinterpret_cast<DWORD*>(pCode + codeSize);
|
||||
|
||||
// New base of ExceptionType array, starts after types array
|
||||
unsigned char* etMem = pCode + codeSize + typeInfoArraySize;
|
||||
int etMemOffset = 0;
|
||||
|
||||
_codeBase = reinterpret_cast<sal_uInt64>(pCode)
|
||||
& ~static_cast<sal_uInt64>(ExceptionInfos::allocationGranularity - 1);
|
||||
|
||||
DWORD old_protect;
|
||||
bool success = VirtualProtect(pCode, codeSize, PAGE_EXECUTE_READWRITE, &old_protect);
|
||||
(void)success;
|
||||
assert(success && "VirtualProtect() failed!");
|
||||
|
||||
::typelib_typedescription_acquire(pTD);
|
||||
|
||||
// Fill pCode with D-Tor code
|
||||
GenerateDestructorTrampoline(pCode, pTD);
|
||||
_pDtor = static_cast<sal_Int32>(reinterpret_cast<sal_uInt64>(pCode) - _codeBase);
|
||||
pCodeOffset += nCodeSnippetSize;
|
||||
|
||||
// Info count accompanied by type info ptrs: type, base type, base base type, ...
|
||||
// Keep offset of types_array
|
||||
_types = static_cast<sal_Int32>(reinterpret_cast<sal_uInt64>(types) - _codeBase);
|
||||
// Fill types: (nLen, _offset to ExceptionType1, ...ExceptionType2, ...)
|
||||
types[0] = nLen;
|
||||
|
||||
int nPos = 1;
|
||||
for (pCompTD = reinterpret_cast<typelib_CompoundTypeDescription*>(pTD); pCompTD;
|
||||
pCompTD = pCompTD->pBaseTypeDescription)
|
||||
{
|
||||
// Create instance in mem block with placement new
|
||||
ExceptionType* et = new (etMem + etMemOffset) ExceptionType(
|
||||
pCode + pCodeOffset, _codeBase, reinterpret_cast<typelib_TypeDescription*>(pCompTD));
|
||||
|
||||
// Next trampoline entry offset
|
||||
pCodeOffset += nCodeSnippetSize;
|
||||
// Next ExceptionType placement offset
|
||||
etMemOffset += exceptionTypeSizeArray[nPos - 1];
|
||||
|
||||
// Keep offset of addresses of ET for D-Tor call in ~RaiseInfo
|
||||
types[nPos++] = static_cast<DWORD>(reinterpret_cast<sal_uInt64>(et) - _codeBase);
|
||||
}
|
||||
// Final check: end of address calculation must be end of mem
|
||||
assert(etMem + etMemOffset == pCode + totalSize);
|
||||
}
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
341
bridges/source/cpp_uno/msvc_win32_arm64/uno2cpp.cxx
Normal file
341
bridges/source/cpp_uno/msvc_win32_arm64/uno2cpp.cxx
Normal file
@ -0,0 +1,341 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <sal/config.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <bridge.hxx>
|
||||
#include <types.hxx>
|
||||
#include <unointerfaceproxy.hxx>
|
||||
#include <vtables.hxx>
|
||||
#include <com/sun/star/uno/Exception.hpp>
|
||||
#include <com/sun/star/uno/RuntimeException.hpp>
|
||||
#include <com/sun/star/uno/genfunc.hxx>
|
||||
#include <rtl/textenc.h>
|
||||
#include <rtl/ustring.hxx>
|
||||
#include <sal/alloca.h>
|
||||
#include <sal/types.h>
|
||||
#include <typelib/typeclass.h>
|
||||
#include <typelib/typedescription.h>
|
||||
#include <uno/any2.h>
|
||||
#include <uno/data.h>
|
||||
|
||||
#include "abi.hxx"
|
||||
#include <msvc/arm64.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
extern "C" void callVirtualFunction(sal_uInt64* stack, sal_uInt64* frame, sal_uInt64 function,
|
||||
void* ret);
|
||||
|
||||
void pushArgument(sal_uInt64 value, sal_uInt64* stack, sal_Int32& sp, sal_uInt64* regs,
|
||||
sal_Int32& nregs)
|
||||
{
|
||||
(nregs != 8 ? regs[nregs++] : stack[sp++]) = value;
|
||||
}
|
||||
|
||||
void call(bridges::cpp_uno::shared::UnoInterfaceProxy* pProxy,
|
||||
bridges::cpp_uno::shared::VtableSlot slot, typelib_TypeDescriptionReference* returnType,
|
||||
const sal_Int32 count, typelib_MethodParameter* parameters, void* returnValue,
|
||||
void** arguments, uno_Any** exception)
|
||||
{
|
||||
static_assert(sizeof(sal_uInt64) == sizeof(void*));
|
||||
typelib_TypeDescription* aReturnTD = nullptr;
|
||||
TYPELIB_DANGER_GET(&aReturnTD, returnType);
|
||||
const ReturnKind eRetKind = getReturnKind(aReturnTD);
|
||||
const bool retConv = bridges::cpp_uno::shared::relatesToInterfaceType(aReturnTD);
|
||||
void* ret = retConv ? alloca(aReturnTD->nSize) : returnValue;
|
||||
|
||||
sal_uInt64** thisPtr = reinterpret_cast<sal_uInt64**>(pProxy->getCppI()) + slot.offset;
|
||||
|
||||
sal_uInt64* gpr = static_cast<sal_uInt64*>(alloca((count + 16) * sizeof(sal_uInt64) + 32));
|
||||
sal_uInt64* fpr = &gpr[8];
|
||||
sal_uInt64* stack = &gpr[16];
|
||||
sal_uInt64* frame = &gpr[16 + count];
|
||||
void** cppArgs = static_cast<void**>(alloca(count * sizeof(void*)));
|
||||
typelib_TypeDescription** ptds
|
||||
= static_cast<typelib_TypeDescription**>(alloca(count * sizeof(typelib_TypeDescription*)));
|
||||
|
||||
sal_Int32 sp = 0;
|
||||
sal_Int32 nGPR = 0;
|
||||
sal_Int32 nFPR = 0;
|
||||
gpr[nGPR++] = reinterpret_cast<sal_uInt64>(thisPtr);
|
||||
|
||||
for (sal_Int32 i = 0; i != count; ++i)
|
||||
{
|
||||
if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
|
||||
{
|
||||
cppArgs[i] = 0;
|
||||
switch (parameters[i].pTypeRef->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
pushArgument(*static_cast<sal_Bool*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_BYTE:
|
||||
pushArgument(*static_cast<sal_Int8*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_SHORT:
|
||||
pushArgument(*static_cast<sal_Int16*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
pushArgument(*static_cast<sal_uInt16*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_ENUM:
|
||||
pushArgument(*static_cast<sal_Int32*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
pushArgument(*static_cast<sal_uInt32*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_HYPER:
|
||||
pushArgument(*static_cast<sal_Int64*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
pushArgument(*static_cast<sal_uInt64*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
pushArgument(*static_cast<sal_uInt32*>(arguments[i]), stack, sp, fpr, nFPR);
|
||||
break;
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
pushArgument(*static_cast<sal_uInt64*>(arguments[i]), stack, sp, fpr, nFPR);
|
||||
break;
|
||||
case typelib_TypeClass_CHAR:
|
||||
pushArgument(*static_cast<sal_Unicode*>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
typelib_TypeDescription* ptd = 0;
|
||||
TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
|
||||
if (!parameters[i].bIn)
|
||||
{
|
||||
cppArgs[i] = alloca(ptd->nSize);
|
||||
uno_constructData(cppArgs[i], ptd);
|
||||
ptds[i] = ptd;
|
||||
pushArgument(reinterpret_cast<sal_uInt64>(cppArgs[i]), stack, sp, gpr, nGPR);
|
||||
}
|
||||
else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd))
|
||||
{
|
||||
cppArgs[i] = alloca(ptd->nSize);
|
||||
uno_copyAndConvertData(cppArgs[i], arguments[i], ptd,
|
||||
pProxy->getBridge()->getUno2Cpp());
|
||||
ptds[i] = ptd;
|
||||
pushArgument(reinterpret_cast<sal_uInt64>(cppArgs[i]), stack, sp, gpr, nGPR);
|
||||
}
|
||||
else
|
||||
{
|
||||
cppArgs[i] = 0;
|
||||
pushArgument(reinterpret_cast<sal_uInt64>(arguments[i]), stack, sp, gpr, nGPR);
|
||||
TYPELIB_DANGER_RELEASE(ptd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__try
|
||||
{
|
||||
callVirtualFunction(stack, frame, (*thisPtr)[slot.index], ret);
|
||||
}
|
||||
__except (msvc_filterCppException(GetExceptionInformation(), *exception,
|
||||
pProxy->getBridge()->getCpp2Uno()))
|
||||
{
|
||||
for (sal_Int32 i = 0; i != count; ++i)
|
||||
{
|
||||
if (cppArgs[i] != 0)
|
||||
{
|
||||
uno_destructData(cppArgs[i], ptds[i],
|
||||
reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
|
||||
TYPELIB_DANGER_RELEASE(ptds[i]);
|
||||
}
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE(aReturnTD);
|
||||
return;
|
||||
}
|
||||
|
||||
*exception = 0;
|
||||
for (sal_Int32 i = 0; i != count; ++i)
|
||||
{
|
||||
if (cppArgs[i] != 0)
|
||||
{
|
||||
if (parameters[i].bOut)
|
||||
{
|
||||
if (parameters[i].bIn)
|
||||
{
|
||||
uno_destructData(arguments[i], ptds[i], 0);
|
||||
}
|
||||
uno_copyAndConvertData(arguments[i], cppArgs[i], ptds[i],
|
||||
pProxy->getBridge()->getCpp2Uno());
|
||||
}
|
||||
uno_destructData(cppArgs[i], ptds[i],
|
||||
reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
|
||||
TYPELIB_DANGER_RELEASE(ptds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
switch (eRetKind)
|
||||
{
|
||||
case RETURN_KIND_REG:
|
||||
switch (aReturnTD->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_VOID:
|
||||
break;
|
||||
case typelib_TypeClass_BOOLEAN:
|
||||
case typelib_TypeClass_BYTE:
|
||||
case typelib_TypeClass_SHORT:
|
||||
case typelib_TypeClass_UNSIGNED_SHORT:
|
||||
case typelib_TypeClass_LONG:
|
||||
case typelib_TypeClass_UNSIGNED_LONG:
|
||||
case typelib_TypeClass_HYPER:
|
||||
case typelib_TypeClass_UNSIGNED_HYPER:
|
||||
case typelib_TypeClass_CHAR:
|
||||
case typelib_TypeClass_ENUM:
|
||||
case typelib_TypeClass_STRUCT:
|
||||
std::memcpy(ret, gpr, aReturnTD->nSize);
|
||||
break;
|
||||
case typelib_TypeClass_FLOAT:
|
||||
case typelib_TypeClass_DOUBLE:
|
||||
std::memcpy(ret, fpr, aReturnTD->nSize);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case RETURN_KIND_HFA_FLOAT:
|
||||
switch (aReturnTD->nSize)
|
||||
{
|
||||
case 16:
|
||||
std::memcpy(static_cast<char*>(ret) + 12, fpr + 3, 4);
|
||||
[[fallthrough]];
|
||||
case 12:
|
||||
std::memcpy(static_cast<char*>(ret) + 8, fpr + 2, 4);
|
||||
[[fallthrough]];
|
||||
case 8:
|
||||
std::memcpy(static_cast<char*>(ret) + 4, fpr + 1, 4);
|
||||
[[fallthrough]];
|
||||
case 4:
|
||||
std::memcpy(ret, fpr, 4);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
case RETURN_KIND_HFA_DOUBLE:
|
||||
std::memcpy(ret, fpr, aReturnTD->nSize);
|
||||
break;
|
||||
case RETURN_KIND_INDIRECT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (retConv)
|
||||
{
|
||||
uno_copyAndConvertData(returnValue, ret, aReturnTD, pProxy->getBridge()->getCpp2Uno());
|
||||
uno_destructData(ret, aReturnTD, reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE(aReturnTD);
|
||||
}
|
||||
}
|
||||
|
||||
namespace bridges::cpp_uno::shared
|
||||
{
|
||||
void unoInterfaceProxyDispatch(uno_Interface* pUnoI, typelib_TypeDescription const* pMemberDescr,
|
||||
void* pReturn, void** pArgs, uno_Any** ppException)
|
||||
{
|
||||
UnoInterfaceProxy* pProxy = static_cast<UnoInterfaceProxy*>(pUnoI);
|
||||
switch (pMemberDescr->eTypeClass)
|
||||
{
|
||||
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
||||
{
|
||||
typelib_InterfaceAttributeTypeDescription const* atd
|
||||
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription const*>(pMemberDescr);
|
||||
VtableSlot slot(getVtableSlot(atd));
|
||||
if (pReturn != 0)
|
||||
{ // getter
|
||||
call(pProxy, slot, atd->pAttributeTypeRef, 0, 0, pReturn, pArgs, ppException);
|
||||
}
|
||||
else
|
||||
{ // setter
|
||||
typelib_MethodParameter param = { 0, atd->pAttributeTypeRef, true, false };
|
||||
typelib_TypeDescriptionReference* pReturnTD = nullptr;
|
||||
typelib_typedescriptionreference_new(&pReturnTD, typelib_TypeClass_VOID,
|
||||
OUString("void").pData);
|
||||
slot.index += 1;
|
||||
call(pProxy, slot, pReturnTD, 1, ¶m, pReturn, pArgs, ppException);
|
||||
typelib_typedescriptionreference_release(pReturnTD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case typelib_TypeClass_INTERFACE_METHOD:
|
||||
{
|
||||
typelib_InterfaceMethodTypeDescription const* mtd
|
||||
= reinterpret_cast<typelib_InterfaceMethodTypeDescription const*>(pMemberDescr);
|
||||
VtableSlot slot(getVtableSlot(mtd));
|
||||
switch (slot.index)
|
||||
{
|
||||
case 1:
|
||||
pUnoI->acquire(pUnoI);
|
||||
*ppException = 0;
|
||||
break;
|
||||
case 2:
|
||||
pUnoI->release(pUnoI);
|
||||
*ppException = 0;
|
||||
break;
|
||||
case 0:
|
||||
{
|
||||
typelib_TypeDescription* td = 0;
|
||||
TYPELIB_DANGER_GET(
|
||||
&td, (reinterpret_cast<css::uno::Type*>(pArgs[0])->getTypeLibType()));
|
||||
if (td != 0)
|
||||
{
|
||||
uno_Interface* ifc = 0;
|
||||
pProxy->pBridge->getUnoEnv()->getRegisteredInterface(
|
||||
pProxy->pBridge->getUnoEnv(), reinterpret_cast<void**>(&ifc),
|
||||
pProxy->oid.pData,
|
||||
reinterpret_cast<typelib_InterfaceTypeDescription*>(td));
|
||||
if (ifc != 0)
|
||||
{
|
||||
uno_any_construct(reinterpret_cast<uno_Any*>(pReturn), &ifc, td, 0);
|
||||
ifc->release(ifc);
|
||||
TYPELIB_DANGER_RELEASE(td);
|
||||
*ppException = 0;
|
||||
break;
|
||||
}
|
||||
TYPELIB_DANGER_RELEASE(td);
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
call(pProxy, slot, mtd->pReturnTypeRef, mtd->nParams, mtd->pParams, pReturn,
|
||||
pArgs, ppException);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
72
bridges/source/cpp_uno/msvc_win32_arm64/vtableslotcall.S
Normal file
72
bridges/source/cpp_uno/msvc_win32_arm64/vtableslotcall.S
Normal file
@ -0,0 +1,72 @@
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
OPT 2 // disable listing
|
||||
// macros to add unwind information
|
||||
#include "ksarm64.h"
|
||||
OPT 1 // re-enable listing
|
||||
|
||||
EXPORT vtableSlotCall
|
||||
IMPORT vtableCall
|
||||
|
||||
TEXTAREA, ALIGN=2
|
||||
|
||||
NESTED_ENTRY vtableSlotCall
|
||||
|
||||
PROLOG_SAVE_REG_PAIR fp, lr, #-192!
|
||||
PROLOG_SAVE_REG_PAIR x19, x20, #16
|
||||
|
||||
add x11, sp, 192
|
||||
add x20, sp, 128
|
||||
add x19, sp, 64
|
||||
|
||||
stp x11, x11, [sp, 32]
|
||||
str x11, [sp, 48]
|
||||
stp wzr, wzr, [sp, 56]
|
||||
stp x0, x1, [sp, 64]
|
||||
mov w0, w9
|
||||
mov w1, w10
|
||||
stp x2, x3, [sp, 80]
|
||||
mov x3, x20
|
||||
mov x2, x19
|
||||
stp x4, x5, [sp, 96]
|
||||
mov x5, x8
|
||||
mov x4, x11
|
||||
stp x6, x7, [sp, 112]
|
||||
stp d0, d1, [sp, 128]
|
||||
stp d2, d3, [sp, 144]
|
||||
stp d4, d5, [sp, 160]
|
||||
stp d6, d7, [sp, 176]
|
||||
|
||||
bl vtableCall
|
||||
|
||||
ldp x0, x1, [x19]
|
||||
ldp d0, d1, [x20]
|
||||
ldp d2, d3, [x20, #16]
|
||||
|
||||
EPILOG_STACK_RESTORE
|
||||
EPILOG_RESTORE_REG_PAIR x19, x20, #16
|
||||
EPILOG_RESTORE_REG_PAIR fp, lr, #192!
|
||||
EPILOG_RETURN
|
||||
|
||||
NESTED_END vtableSlotCall
|
||||
|
||||
END
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab */
|
@ -134,6 +134,21 @@ fi
|
||||
endef
|
||||
|
||||
# AsmObject class
|
||||
ifeq ($(CPUNAME),ARM64)
|
||||
gb_AsmObject_get_source = $(1)/$(2).S
|
||||
|
||||
# Code needs a preprozessor step .S -> .asm -> .o
|
||||
define gb_AsmObject__command
|
||||
$(call gb_Output_announce,$(2),$(true),ASM,3)
|
||||
$(call gb_Helper_abbreviate_dirs,\
|
||||
mkdir -p $(dir $(1)) $(dir $(4)) && \
|
||||
"$(CC)" -nologo -EP -D_M_ARM64 $(SOLARINC) $(3) > $(subst .o,.asm,$(1)) && \
|
||||
"$(ML_EXE)" $(gb_AFLAGS) -g -errorReport:prompt -o $(1) $(subst .o,.asm,$(1)), \
|
||||
) && \
|
||||
echo "$(1) : $(3)" > $(4)
|
||||
endef
|
||||
|
||||
else # !ARM64
|
||||
gb_AsmObject_get_source = $(1)/$(2).asm
|
||||
|
||||
define gb_AsmObject__command
|
||||
@ -146,6 +161,7 @@ $(call gb_Helper_abbreviate_dirs,\
|
||||
echo "$(1) : $(3)" > $(4)
|
||||
endef
|
||||
|
||||
endif
|
||||
|
||||
# LinkTarget class
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user