summaryrefslogtreecommitdiff
path: root/bridges
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2020-11-12 23:49:57 +0200
committerTor Lillqvist <tml@collabora.com>2020-11-13 20:01:51 +0100
commite0df85554b533fab67a5a91193024e4876c5ec02 (patch)
treeb75e8af70a385d0ae6f48a9aaa98ef62088fd3b5 /bridges
parent76fc34baeb4257e71092690b7039c0befe371bae (diff)
Improve the C++/UNO bridge for macOS on Apple Silicon
Now bridgetest (as improved by my previous commit) passes. That doesn't necessarily prove much, though, I am sure there are interesting corner cases that it doesn't exercise. Anyway, making this work was easier than I had feared. Unlike the arm64 ABI used on Linux, on macOS (and iOS, but we don't really use the C++/UNO bridge for iOS) we need to pack parameters smaller than eight bytes according to their natural alignment. Bytes take one byte, shorts two bytes aligned at a two-byte boundary, etc. Change-Id: I5b7dc2f8fce41ddec88df0e688898a074d8b2dad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105773 Tested-by: Tor Lillqvist <tml@collabora.com> Reviewed-by: Tor Lillqvist <tml@collabora.com>
Diffstat (limited to 'bridges')
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx139
-rw-r--r--bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx121
2 files changed, 258 insertions, 2 deletions
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
index a67f2ca611ea..830c42eb52f8 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
@@ -70,11 +70,142 @@ void call(
sal_Int32 ngpr = 1;
sal_Int32 nfpr = 0;
sal_Int32 sp = 0;
+#ifdef MACOSX
+ sal_Int32 subsp = 0;
+#endif
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) {
+#ifdef MACOSX
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ if (ngpr < 8)
+ {
+ args[i] = gpr + ngpr;
+ ngpr++;
+ }
+ else
+ {
+ args[i] = reinterpret_cast<void **>(reinterpret_cast<uintptr_t>(stack + sp) + subsp);
+ subsp += 1;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ }
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_CHAR:
+ if (ngpr < 8)
+ {
+ args[i] = gpr + ngpr;
+ ngpr++;
+ }
+ else
+ {
+ subsp = (subsp + 1) & ~0x1;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ args[i] = reinterpret_cast<void **>(reinterpret_cast<uintptr_t>(stack + sp) + subsp);
+ subsp += 2;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ }
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ if (ngpr < 8)
+ {
+ args[i] = gpr + ngpr;
+ ngpr++;
+ }
+ else
+ {
+ subsp = (subsp + 3) & ~0x3;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ args[i] = reinterpret_cast<void **>(reinterpret_cast<uintptr_t>(stack + sp) + subsp);
+ subsp += 4;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ }
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ if (ngpr < 8)
+ {
+ args[i] = gpr + ngpr;
+ ngpr++;
+ }
+ else
+ {
+ if (subsp > 0)
+ {
+ sp++;
+ subsp = 0;
+ }
+ args[i] = stack + sp;
+ sp++;
+ }
+ break;
+ case typelib_TypeClass_FLOAT:
+ if (nfpr < 8)
+ {
+ args[i] = fpr + nfpr;
+ nfpr++;
+ }
+ else
+ {
+ subsp = (subsp + 3) & ~0x3;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ args[i] = reinterpret_cast<void **>(reinterpret_cast<uintptr_t>(stack + sp) + subsp);
+ subsp += 4;
+ if (subsp == 8)
+ {
+ sp++;
+ subsp = 0;
+ }
+ }
+ break;
+ case typelib_TypeClass_DOUBLE:
+ if (nfpr < 8)
+ {
+ args[i] = fpr + nfpr;
+ nfpr++;
+ }
+ else
+ {
+ if (subsp > 0)
+ {
+ sp++;
+ subsp = 0;
+ }
+ args[i] = stack + sp;
+ sp++;
+ }
+ break;
+#else
case typelib_TypeClass_BOOLEAN:
case typelib_TypeClass_BYTE:
case typelib_TypeClass_SHORT:
@@ -91,11 +222,19 @@ void call(
case typelib_TypeClass_DOUBLE:
args[i] = nfpr == 8 ? stack + sp++ : fpr + nfpr++;
break;
+#endif
default:
assert(false);
}
argtds[i] = 0;
} else {
+#ifdef MACOSX
+ if (subsp > 0)
+ {
+ sp++;
+ subsp = 0;
+ }
+#endif
cppArgs[i] = reinterpret_cast<void *>(
ngpr == 8 ? stack[sp++] : gpr[ngpr++]);
typelib_TypeDescription * ptd = 0;
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
index 760a7b38551d..14e4afa46cc0 100644
--- a/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
@@ -46,10 +46,82 @@
namespace {
void pushArgument(
- unsigned long value, unsigned long * stack, sal_Int32 * sp,
- unsigned long * regs, sal_Int32 * nregs)
+#ifdef MACOSX
+ typelib_TypeClass typeclass,
+ sal_Int32 * const subsp,
+#endif
+ unsigned long value, unsigned long * const stack, sal_Int32 * const sp,
+ unsigned long * const regs, sal_Int32 * const nregs)
{
+#ifdef MACOSX
+ if (*nregs != 8)
+ {
+ regs[(*nregs)++] = value;
+ }
+ else
+ {
+ switch (typeclass) {
+ case typelib_TypeClass_BOOLEAN:
+ case typelib_TypeClass_BYTE:
+ *reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value;
+ (*subsp) += 1;
+ if (*subsp == 8)
+ {
+ (*sp)++;
+ *subsp = 0;
+ }
+ break;
+ case typelib_TypeClass_SHORT:
+ case typelib_TypeClass_UNSIGNED_SHORT:
+ case typelib_TypeClass_CHAR:
+ *subsp = (*subsp + 1) & ~0x1;
+ if (*subsp == 8)
+ {
+ (*sp)++;
+ *subsp = 0;
+ }
+ *reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value;
+ (*subsp) += 2;
+ if (*subsp == 8)
+ {
+ (*sp)++;
+ *subsp = 0;
+ }
+ break;
+ case typelib_TypeClass_LONG:
+ case typelib_TypeClass_UNSIGNED_LONG:
+ case typelib_TypeClass_ENUM:
+ case typelib_TypeClass_FLOAT:
+ *subsp = (*subsp + 3) & ~0x3;
+ if (*subsp == 8)
+ {
+ (*sp)++;
+ *subsp = 0;
+ }
+ *reinterpret_cast<uint32_t*>(reinterpret_cast<uintptr_t>(stack + *sp) + *subsp) = value;
+ (*subsp) += 4;
+ if (*subsp == 8)
+ {
+ (*sp)++;
+ *subsp = 0;
+ }
+ break;
+ case typelib_TypeClass_HYPER:
+ case typelib_TypeClass_UNSIGNED_HYPER:
+ default:
+ if (*subsp > 0)
+ {
+ (*sp)++;
+ *subsp = 0;
+ }
+ stack[*sp] = value;
+ (*sp)++;
+ break;
+ }
+ }
+#else
(*nregs != 8 ? regs[(*nregs)++] : stack[(*sp)++]) = value;
+#endif
}
void call(
@@ -69,6 +141,9 @@ void call(
unsigned long * stack = static_cast<unsigned long *>(
alloca(count * sizeof (unsigned long)));
sal_Int32 sp = 0;
+#ifdef MACOSX
+ sal_Int32 subsp = 0;
+#endif
unsigned long gpr[8];
sal_Int32 ngpr = 0;
unsigned long fpr[8];
@@ -86,57 +161,90 @@ void call(
switch (parameters[i].pTypeRef->eTypeClass) {
case typelib_TypeClass_BOOLEAN:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_Bool *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_BYTE:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_Int8 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_SHORT:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_Int16 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_UNSIGNED_SHORT:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_uInt16 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_LONG:
case typelib_TypeClass_ENUM:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_Int32 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_UNSIGNED_LONG:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_uInt32 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_HYPER:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_Int64 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_UNSIGNED_HYPER:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_uInt64 *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
case typelib_TypeClass_FLOAT:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<unsigned int *>(arguments[i]), stack, &sp, fpr,
&nfpr);
break;
case typelib_TypeClass_DOUBLE:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<unsigned long *>(arguments[i]), stack, &sp,
fpr, &nfpr);
break;
case typelib_TypeClass_CHAR:
pushArgument(
+#ifdef MACOSX
+ parameters[i].pTypeRef->eTypeClass, &subsp,
+#endif
*static_cast<sal_Unicode *>(arguments[i]), stack, &sp, gpr,
&ngpr);
break;
@@ -151,6 +259,9 @@ void call(
uno_constructData(cppArgs[i], ptd);
ptds[i] = ptd;
pushArgument(
+#ifdef MACOSX
+ typelib_TypeClass_HYPER, &subsp,
+#endif
reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp,
gpr, &ngpr);
} else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) {
@@ -160,11 +271,17 @@ void call(
proxy->getBridge()->getUno2Cpp());
ptds[i] = ptd;
pushArgument(
+#ifdef MACOSX
+ typelib_TypeClass_HYPER, &subsp,
+#endif
reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp,
gpr, &ngpr);
} else {
cppArgs[i] = 0;
pushArgument(
+#ifdef MACOSX
+ typelib_TypeClass_HYPER, &subsp,
+#endif
reinterpret_cast<unsigned long>(arguments[i]), stack, &sp,
gpr, &ngpr);
TYPELIB_DANGER_RELEASE(ptd);