diff options
author | Tor Lillqvist <tml@collabora.com> | 2020-11-12 23:49:57 +0200 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2020-11-13 20:01:51 +0100 |
commit | e0df85554b533fab67a5a91193024e4876c5ec02 (patch) | |
tree | b75e8af70a385d0ae6f48a9aaa98ef62088fd3b5 /bridges | |
parent | 76fc34baeb4257e71092690b7039c0befe371bae (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.cxx | 139 | ||||
-rw-r--r-- | bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx | 121 |
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); |