summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
Diffstat (limited to 'bridges')
-rw-r--r--bridges/CustomTarget_gcc3_wasm.mk26
-rw-r--r--bridges/Library_cpp_uno.mk6
-rw-r--r--bridges/Module_bridges.mk1
-rw-r--r--bridges/inc/wasm/callvirtualfunction.hxx21
-rw-r--r--bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx226
5 files changed, 279 insertions, 1 deletions
diff --git a/bridges/CustomTarget_gcc3_wasm.mk b/bridges/CustomTarget_gcc3_wasm.mk
new file mode 100644
index 000000000000..a88da8577282
--- /dev/null
+++ b/bridges/CustomTarget_gcc3_wasm.mk
@@ -0,0 +1,26 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; 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/.
+#
+
+$(eval $(call gb_CustomTarget_CustomTarget,bridges/gcc3_wasm))
+
+$(eval $(call gb_CustomTarget_register_targets,bridges/gcc3_wasm, \
+ callvirtualfunction-wrapper.cxx \
+ callvirtualfunction-impls.s \
+))
+
+$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-impls.s \
+$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-wrapper.cxx: \
+ $(call gb_Executable_get_target_for_build,wasmcallgen) $(call gb_UnoApi_get_target,udkapi) \
+ $(call gb_UnoApi_get_target,offapi)
+ $(call gb_Executable_get_command,wasmcallgen) \
+ $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-wrapper.cxx \
+ $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-impls.s \
+ +$(call gb_UnoApi_get_target,udkapi) +$(call gb_UnoApi_get_target,offapi)
+
+# vim: set noet sw=4 ts=4:
diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
index dcf83cf34e5b..c42778f359c1 100644
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -84,6 +84,12 @@ bridge_noopt_objects := except
else ifeq ($(OS),EMSCRIPTEN)
bridges_SELECTED_BRIDGE := gcc3_wasm
bridge_noopt_objects := cpp2uno except uno2cpp
+$(eval $(call gb_Library_add_generated_asmobjects,$(CPPU_ENV)_uno, \
+ CustomTarget/bridges/gcc3_wasm/callvirtualfunction-impls \
+))
+$(eval $(call gb_Library_add_generated_exception_objects,$(CPPU_ENV)_uno, \
+ CustomTarget/bridges/gcc3_wasm/callvirtualfunction-wrapper \
+))
endif
else ifeq ($(CPUNAME),M68K)
diff --git a/bridges/Module_bridges.mk b/bridges/Module_bridges.mk
index 3016bf2c404f..def86fea4cb7 100644
--- a/bridges/Module_bridges.mk
+++ b/bridges/Module_bridges.mk
@@ -20,6 +20,7 @@ $(eval $(call gb_Module_add_targets,bridges,\
$(if $(filter ANDROID LINUX,$(OS)),\
CustomTarget_gcc3_linux_arm) \
) \
+ $(if $(filter EMSCRIPTEN,$(OS)),CustomTarget_gcc3_wasm) \
))
ifeq (,$(filter build,$(gb_Module_SKIPTARGETS)))
diff --git a/bridges/inc/wasm/callvirtualfunction.hxx b/bridges/inc/wasm/callvirtualfunction.hxx
new file mode 100644
index 000000000000..23b446cd45b3
--- /dev/null
+++ b/bridges/inc/wasm/callvirtualfunction.hxx
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 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/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <sal/types.h>
+
+void callVirtualFunction(std::string_view signature, sal_uInt32 target, sal_uInt64 const* arguments,
+ void* returnValue);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx
index ddb51166b51e..41a471bcc9b0 100644
--- a/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx
+++ b/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx
@@ -7,15 +7,81 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+#include <sal/config.h>
+
+#include <vector>
+
#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Type.hxx>
+#include <o3tl/unreachable.hxx>
+#include <rtl/strbuf.hxx>
+#include <typelib/typeclass.h>
+#include <typelib/typedescription.h>
#include <bridge.hxx>
#include <types.hxx>
#include <unointerfaceproxy.hxx>
#include <vtables.hxx>
+#include <wasm/callvirtualfunction.hxx>
+
using namespace ::com::sun::star::uno;
+namespace
+{
+enum class StructKind
+{
+ Empty,
+ I32,
+ I64,
+ F32,
+ F64,
+ General
+};
+
+StructKind getKind(typelib_CompoundTypeDescription const* type)
+{
+ if (type->nMembers > 1)
+ {
+ return StructKind::General;
+ }
+ auto k = StructKind::Empty;
+ if (type->pBaseTypeDescription != nullptr)
+ {
+ k = getKind(type->pBaseTypeDescription);
+ }
+ if (type->nMembers == 0)
+ {
+ return k;
+ }
+ if (k != StructKind::Empty)
+ {
+ return StructKind::General;
+ }
+ switch (type->ppTypeRefs[0]->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_CHAR:
+ case typelib_TypeClass_ENUM:
+ return StructKind::I32;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ return StructKind::I64;
+ case typelib_TypeClass_FLOAT:
+ return StructKind::F32;
+ case typelib_TypeClass_DOUBLE:
+ return StructKind::F64;
+ default:
+ return StructKind::General;
+ }
+}
+}
+
namespace bridges::cpp_uno::shared
{
void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescription* pMemberDescr,
@@ -71,7 +137,165 @@ void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescripti
} // else perform queryInterface()
[[fallthrough]];
default:
- std::abort();
+ {
+ auto const mtd
+ = reinterpret_cast<typelib_InterfaceMethodTypeDescription const*>(
+ pMemberDescr);
+ OStringBuffer sig;
+ std::vector<sal_uInt64> args;
+ switch (mtd->pReturnTypeRef->eTypeClass)
+ {
+ case typelib_TypeClass_VOID:
+ sig.append('v');
+ 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_CHAR:
+ case typelib_TypeClass_ENUM:
+ sig.append('i');
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ sig.append('j');
+ break;
+ case typelib_TypeClass_FLOAT:
+ sig.append('f');
+ break;
+ case typelib_TypeClass_DOUBLE:
+ sig.append('d');
+ break;
+ case typelib_TypeClass_STRING:
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_INTERFACE:
+ sig.append("vi");
+ args.push_back(reinterpret_cast<sal_uInt32>(pReturn));
+ break;
+ case typelib_TypeClass_STRUCT:
+ {
+ typelib_TypeDescription* td = nullptr;
+ css::uno::Type(mtd->pReturnTypeRef).getDescription(&td);
+ switch (getKind(
+ reinterpret_cast<typelib_CompoundTypeDescription const*>(td)))
+ {
+ case StructKind::Empty:
+ break;
+ case StructKind::I32:
+ sig.append('i');
+ break;
+ case StructKind::I64:
+ sig.append('j');
+ break;
+ case StructKind::F32:
+ sig.append('f');
+ break;
+ case StructKind::F64:
+ sig.append('d');
+ break;
+ case StructKind::General:
+ sig.append("vi");
+ args.push_back(reinterpret_cast<sal_uInt32>(pReturn));
+ break;
+ }
+ break;
+ }
+ default:
+ O3TL_UNREACHABLE;
+ }
+ sig.append('i');
+ args.push_back(reinterpret_cast<sal_uInt32>(pThis->pCppI));
+ for (sal_Int32 i = 0; i != mtd->nParams; ++i)
+ {
+ if (mtd->pParams[i].bOut)
+ {
+ sig.append('i');
+ args.push_back(reinterpret_cast<sal_uInt32>(pArgs[i]));
+ }
+ else
+ {
+ switch (mtd->pParams[i].pTypeRef->eTypeClass)
+ {
+ case typelib_TypeClass_BOOLEAN:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_Bool const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_BYTE:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_Int8 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_SHORT:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_Int16 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_uInt16 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_ENUM:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_Int32 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_UNSIGNED_LONG:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_uInt32 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_HYPER:
+ sig.append('j');
+ args.push_back(*reinterpret_cast<sal_Int64 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ sig.append('j');
+ args.push_back(*reinterpret_cast<sal_uInt64 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_FLOAT:
+ sig.append('f');
+ args.push_back(*reinterpret_cast<sal_uInt32 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_DOUBLE:
+ sig.append('d');
+ args.push_back(*reinterpret_cast<sal_uInt64 const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_CHAR:
+ sig.append('i');
+ args.push_back(*reinterpret_cast<sal_Unicode const*>(pArgs[i]));
+ break;
+ case typelib_TypeClass_STRING:
+ case typelib_TypeClass_TYPE:
+ case typelib_TypeClass_ANY:
+ case typelib_TypeClass_SEQUENCE:
+ case typelib_TypeClass_STRUCT:
+ case typelib_TypeClass_INTERFACE:
+ sig.append('i');
+ args.push_back(reinterpret_cast<sal_uInt32>(pArgs[i]));
+ break;
+ default:
+ O3TL_UNREACHABLE;
+ }
+ }
+ }
+ try
+ {
+ callVirtualFunction(sig,
+ (*reinterpret_cast<sal_uInt32 const* const*>(
+ pThis->pCppI))[aVtableSlot.index],
+ args.data(), pReturn);
+ *ppException = nullptr;
+ }
+ catch (...)
+ {
+ css::uno::RuntimeException TODO("Wasm bridge TODO");
+ uno_type_any_construct(
+ *ppException, &TODO,
+ cppu::UnoType<css::uno::RuntimeException>::get().getTypeLibType(),
+ nullptr);
+ }
+ }
}
break;
}