f085be
From 09f49fc55104ee7b0fe18dbb5068a4cad7d9fc25 Mon Sep 17 00:00:00 2001
f085be
From: Stephan Bergmann <sbergman@redhat.com>
f085be
Date: Fri, 29 Aug 2014 17:17:42 +0200
f085be
Subject: [PATCH 2/2] Linux AArch64 port
f085be
f085be
(cherry picked from commit 235fa0334e0b45c736b636ba1689e2f8c7458697)
f085be
Conflicts:
f085be
        bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
f085be
        bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
f085be
        bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
f085be
	configure.ac
f085be
f085be
Change-Id: I37044a37348b203944a8eb9d2204e619055f069d
f085be
---
f085be
 bridges/Library_cpp_uno.mk                         |   5 +
f085be
 bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx  | 310 ++++++++++++++
f085be
 bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx  |  87 ++++
f085be
 .../gcc3_linux_aarch64/callvirtualfunction.cxx     |  66 +++
f085be
 .../gcc3_linux_aarch64/callvirtualfunction.hxx     |  33 ++
f085be
 .../source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx  | 464 +++++++++++++++++++++
f085be
 .../source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx  | 376 +++++++++++++++++
f085be
 configure.ac                                       |   6 +
f085be
 desktop/source/deployment/misc/dp_platform.cxx     |   4 +-
f085be
 jvmfwk/plugins/sunmajor/pluginlib/vendorbase.hxx   |   2 +
f085be
 solenv/gbuild/platform/LINUX_AARCH64_GCC.mk        |  14 +
f085be
 11 files changed, 1366 insertions(+), 1 deletion(-)
f085be
 create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
f085be
 create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
f085be
 create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx
f085be
 create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx
f085be
 create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
f085be
 create mode 100644 bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
f085be
 create mode 100644 solenv/gbuild/platform/LINUX_AARCH64_GCC.mk
f085be
f085be
diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
f085be
index c6ab9a0..0fcaf6b 100644
f085be
--- a/bridges/Library_cpp_uno.mk
f085be
+++ b/bridges/Library_cpp_uno.mk
f085be
@@ -35,6 +35,11 @@ $(call gb_LinkTarget_get_target,$(call gb_Library_get_linktarget,gcc3_uno)) : \
f085be
 	EXTRAOBJECTLISTS += $(call gb_CustomTarget_get_workdir,bridges/source/cpp_uno/gcc3_linux_arm)/armhelper.objectlist
f085be
 endif
f085be
 
f085be
+else ifeq ($(OS)-$(CPUNAME),LINUX-AARCH64)
f085be
+
f085be
+bridges_SELECTED_BRIDGE := gcc3_linux_aarch64
f085be
+bridge_exception_objects := abi callvirtualfunction cpp2uno uno2cpp
f085be
+
f085be
 else ifeq ($(OS)-$(CPUNAME),LINUX-AXP)
f085be
 
f085be
 bridges_SELECTED_BRIDGE := gcc3_linux_alpha
f085be
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
f085be
new file mode 100644
f085be
index 0000000..c177b22
f085be
--- /dev/null
f085be
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.cxx
f085be
@@ -0,0 +1,310 @@
f085be
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
f085be
+/*
f085be
+ * This file is part of the LibreOffice project.
f085be
+ *
f085be
+ * This Source Code Form is subject to the terms of the Mozilla Public
f085be
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+ *
f085be
+ * This file incorporates work covered by the following license notice:
f085be
+ *
f085be
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
f085be
+ *   contributor license agreements. See the NOTICE file distributed
f085be
+ *   with this work for additional information regarding copyright
f085be
+ *   ownership. The ASF licenses this file to you under the Apache
f085be
+ *   License, Version 2.0 (the "License"); you may not use this file
f085be
+ *   except in compliance with the License. You may obtain a copy of
f085be
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
f085be
+ */
f085be
+
f085be
+#include <sal/config.h>
f085be
+
f085be
+#include <cassert>
f085be
+#include <cstddef>
f085be
+#include <cstring>
f085be
+#include <typeinfo>
f085be
+
f085be
+#include <cxxabi.h>
f085be
+#include <dlfcn.h>
f085be
+
f085be
+#include <boost/unordered_map.hpp>
f085be
+#include <com/sun/star/uno/RuntimeException.hpp>
f085be
+#include <com/sun/star/uno/genfunc.h>
f085be
+#include <rtl/strbuf.hxx>
f085be
+#include <rtl/ustrbuf.hxx>
f085be
+#include <rtl/ustring.hxx>
f085be
+#include <sal/types.h>
f085be
+#include <typelib/typeclass.h>
f085be
+#include <typelib/typedescription.h>
f085be
+#include <uno/any2.h>
f085be
+#include <uno/mapping.h>
f085be
+
f085be
+#include <abi.hxx>
f085be
+
f085be
+namespace {
f085be
+
f085be
+OUString toUnoName(char const * name) {
f085be
+    assert(name != 0);
f085be
+    OUStringBuffer b;
f085be
+    bool scoped = *name == 'N';
f085be
+    if (scoped) {
f085be
+        ++name;
f085be
+    }
f085be
+    for (;;) {
f085be
+        assert(*name >= '0' && *name <= '9');
f085be
+        std::size_t n = *name++ - '0';
f085be
+        while (*name >= '0' && *name <= '9') {
f085be
+            n = 10 * n + (*name++ - '0');
f085be
+        }
f085be
+        b.appendAscii(name, n);
f085be
+        name += n;
f085be
+        if (!scoped) {
f085be
+            assert(*name == 0);
f085be
+            break;
f085be
+        }
f085be
+        if (*name == 'E') {
f085be
+            assert(name[1] == 0);
f085be
+            break;
f085be
+        }
f085be
+        b.append('.');
f085be
+    }
f085be
+    return b.makeStringAndClear();
f085be
+}
f085be
+
f085be
+class Rtti {
f085be
+public:
f085be
+    Rtti(): app_(dlopen(0, RTLD_LAZY)) {}
f085be
+
f085be
+    ~Rtti() { dlclose(app_); }
f085be
+
f085be
+    std::type_info * getRtti(typelib_TypeDescription const & type);
f085be
+
f085be
+private:
f085be
+    typedef boost::unordered_map<OUString, std::type_info *, OUStringHash> Map;
f085be
+
f085be
+    void * app_;
f085be
+
f085be
+    osl::Mutex mutex_;
f085be
+    Map map_;
f085be
+};
f085be
+
f085be
+std::type_info * Rtti::getRtti(typelib_TypeDescription const & type) {
f085be
+    OUString unoName(type.pTypeName);
f085be
+    osl::MutexGuard g(mutex_);
f085be
+    Map::iterator i(map_.find(unoName));
f085be
+    if (i == map_.end()) {
f085be
+        OStringBuffer b;
f085be
+        b.append("_ZTIN");
f085be
+        for (sal_Int32 j = 0; j != -1;) {
f085be
+            OString t(
f085be
+                OUStringToOString(
f085be
+                    unoName.getToken(0, '.', j), RTL_TEXTENCODING_ASCII_US));
f085be
+            b.append(t.getLength());
f085be
+            b.append(t);
f085be
+        }
f085be
+        b.append('E');
f085be
+        OString sym(b.makeStringAndClear());
f085be
+        std::type_info * rtti = static_cast<std::type_info *>(
f085be
+            dlsym(app_, sym.getStr()));
f085be
+        if (rtti == 0) {
f085be
+            char const * rttiName = sym.getStr() + std::strlen("_ZTI");
f085be
+            assert(type.eTypeClass == typelib_TypeClass_EXCEPTION);
f085be
+            typelib_CompoundTypeDescription const & ctd
f085be
+                = reinterpret_cast<typelib_CompoundTypeDescription const &>(
f085be
+                    type);
f085be
+            if (ctd.pBaseTypeDescription == 0) {
f085be
+                rtti = new __cxxabiv1::__class_type_info(strdup(rttiName));
f085be
+            } else {
f085be
+                std::type_info * base = getRtti(
f085be
+                    ctd.pBaseTypeDescription->aBase);
f085be
+                rtti = new __cxxabiv1::__si_class_type_info(
f085be
+                    strdup(rttiName),
f085be
+                    static_cast<__cxxabiv1::__class_type_info *>(base));
f085be
+            }
f085be
+        }
f085be
+        i = map_.insert(Map::value_type(unoName, rtti)).first;
f085be
+    }
f085be
+    return i->second;
f085be
+}
f085be
+
f085be
+struct theRttiFactory: public rtl::Static<Rtti, theRttiFactory> {};
f085be
+
f085be
+std::type_info * getRtti(typelib_TypeDescription const & type) {
f085be
+    return theRttiFactory::get().getRtti(type);
f085be
+}
f085be
+
f085be
+extern "C" void _GLIBCXX_CDTOR_CALLABI deleteException(void * exception) {
f085be
+    abi_aarch64::__cxa_exception * header =
f085be
+        static_cast<abi_aarch64::__cxa_exception *>(exception) - 1;
f085be
+    OUString unoName(toUnoName(header->exceptionType->name()));
f085be
+    typelib_TypeDescription * td = 0;
f085be
+    typelib_typedescription_getByName(&td, unoName.pData);
f085be
+    assert(td != 0);
f085be
+    uno_destructData(exception, td, &css::uno::cpp_release);
f085be
+    typelib_typedescription_release(td);
f085be
+}
f085be
+
f085be
+enum StructKind {
f085be
+    STRUCT_KIND_EMPTY, STRUCT_KIND_FLOAT, STRUCT_KIND_DOUBLE, STRUCT_KIND_POD,
f085be
+    STRUCT_KIND_DTOR
f085be
+};
f085be
+
f085be
+StructKind getStructKind(typelib_CompoundTypeDescription const * type) {
f085be
+    StructKind k = type->pBaseTypeDescription == 0
f085be
+        ? STRUCT_KIND_EMPTY : getStructKind(type->pBaseTypeDescription);
f085be
+    for (sal_Int32 i = 0; i != type->nMembers; ++i) {
f085be
+        StructKind k2 = StructKind();
f085be
+        switch (type->ppTypeRefs[i]->eTypeClass) {
f085be
+        case typelib_TypeClass_BOOLEAN:
f085be
+        case typelib_TypeClass_BYTE:
f085be
+        case typelib_TypeClass_SHORT:
f085be
+        case typelib_TypeClass_UNSIGNED_SHORT:
f085be
+        case typelib_TypeClass_LONG:
f085be
+        case typelib_TypeClass_UNSIGNED_LONG:
f085be
+        case typelib_TypeClass_HYPER:
f085be
+        case typelib_TypeClass_UNSIGNED_HYPER:
f085be
+        case typelib_TypeClass_CHAR:
f085be
+        case typelib_TypeClass_ENUM:
f085be
+            k2 = STRUCT_KIND_POD;
f085be
+            break;
f085be
+        case typelib_TypeClass_FLOAT:
f085be
+            k2 = STRUCT_KIND_FLOAT;
f085be
+            break;
f085be
+        case typelib_TypeClass_DOUBLE:
f085be
+            k2 = STRUCT_KIND_DOUBLE;
f085be
+            break;
f085be
+        case typelib_TypeClass_STRING:
f085be
+        case typelib_TypeClass_TYPE:
f085be
+        case typelib_TypeClass_ANY:
f085be
+        case typelib_TypeClass_SEQUENCE:
f085be
+        case typelib_TypeClass_INTERFACE:
f085be
+            k2 = STRUCT_KIND_DTOR;
f085be
+            break;
f085be
+        case typelib_TypeClass_STRUCT:
f085be
+            {
f085be
+                typelib_TypeDescription * td = 0;
f085be
+                TYPELIB_DANGER_GET(&td, type->ppTypeRefs[i]);
f085be
+                k2 = getStructKind(
f085be
+                    reinterpret_cast<typelib_CompoundTypeDescription const *>(
f085be
+                        td));
f085be
+                TYPELIB_DANGER_RELEASE(td);
f085be
+                break;
f085be
+            }
f085be
+        default:
f085be
+            assert(false);
f085be
+        }
f085be
+        switch (k2) {
f085be
+        case STRUCT_KIND_EMPTY:
f085be
+            // this means an empty sub-object, which nevertheless obtains a byte
f085be
+            // of storage (TODO: does it?), so the full object cannot be a
f085be
+            // homogenous collection of float or double
f085be
+        case STRUCT_KIND_POD:
f085be
+            assert(k != STRUCT_KIND_DTOR);
f085be
+            k = STRUCT_KIND_POD;
f085be
+            break;
f085be
+        case STRUCT_KIND_FLOAT:
f085be
+        case STRUCT_KIND_DOUBLE:
f085be
+            if (k == STRUCT_KIND_EMPTY) {
f085be
+                k = k2;
f085be
+            } else if (k != k2) {
f085be
+                assert(k != STRUCT_KIND_DTOR);
f085be
+                k = STRUCT_KIND_POD;
f085be
+            }
f085be
+            break;
f085be
+        case STRUCT_KIND_DTOR:
f085be
+            return STRUCT_KIND_DTOR;
f085be
+        }
f085be
+    }
f085be
+    return k;
f085be
+}
f085be
+
f085be
+}
f085be
+
f085be
+namespace abi_aarch64 {
f085be
+
f085be
+void mapException(
f085be
+    __cxa_exception * exception, uno_Any * any, uno_Mapping * mapping)
f085be
+{
f085be
+    assert(exception != 0);
f085be
+    OUString unoName(toUnoName(exception->exceptionType->name()));
f085be
+    typelib_TypeDescription * td = 0;
f085be
+    typelib_typedescription_getByName(&td, unoName.pData);
f085be
+    if (td == 0) {
f085be
+        css::uno::RuntimeException e(
f085be
+            "exception type not found: " + unoName,
f085be
+            css::uno::Reference<css::uno::XInterface>());
f085be
+        uno_type_any_constructAndConvert(
f085be
+            any, &e,
f085be
+            cppu::UnoType<css::uno::RuntimeException>::get().getTypeLibType(),
f085be
+            mapping);
f085be
+    } else {
f085be
+        uno_any_constructAndConvert(any, exception->adjustedPtr, td, mapping);
f085be
+        typelib_typedescription_release(td);
f085be
+    }
f085be
+}
f085be
+
f085be
+void raiseException(uno_Any * any, uno_Mapping * mapping) {
f085be
+    typelib_TypeDescription * td = 0;
f085be
+    TYPELIB_DANGER_GET(&td, any->pType);
f085be
+    if (td == 0) {
f085be
+        throw css::uno::RuntimeException(
f085be
+            "no typedescription for " + OUString(any->pType->pTypeName),
f085be
+            css::uno::Reference<css::uno::XInterface>());
f085be
+    }
f085be
+    void * exc = __cxxabiv1::__cxa_allocate_exception(td->nSize);
f085be
+    uno_copyAndConvertData(exc, any->pData, td, mapping);
f085be
+    uno_any_destruct(any, 0);
f085be
+    std::type_info * rtti = getRtti(*td);
f085be
+    TYPELIB_DANGER_RELEASE(td);
f085be
+    __cxxabiv1::__cxa_throw(exc, rtti, deleteException);
f085be
+}
f085be
+
f085be
+ReturnKind getReturnKind(typelib_TypeDescription const * type) {
f085be
+    switch (type->eTypeClass) {
f085be
+    default:
f085be
+        assert(false);
f085be
+        // fall through to avoid warnings
f085be
+    case typelib_TypeClass_VOID:
f085be
+    case typelib_TypeClass_BOOLEAN:
f085be
+    case typelib_TypeClass_BYTE:
f085be
+    case typelib_TypeClass_SHORT:
f085be
+    case typelib_TypeClass_UNSIGNED_SHORT:
f085be
+    case typelib_TypeClass_LONG:
f085be
+    case typelib_TypeClass_UNSIGNED_LONG:
f085be
+    case typelib_TypeClass_HYPER:
f085be
+    case typelib_TypeClass_UNSIGNED_HYPER:
f085be
+    case typelib_TypeClass_FLOAT:
f085be
+    case typelib_TypeClass_DOUBLE:
f085be
+    case typelib_TypeClass_CHAR:
f085be
+    case typelib_TypeClass_ENUM:
f085be
+        assert(type->nSize <= 16);
f085be
+        return RETURN_KIND_REG;
f085be
+    case typelib_TypeClass_STRING:
f085be
+    case typelib_TypeClass_TYPE:
f085be
+    case typelib_TypeClass_ANY:
f085be
+    case typelib_TypeClass_SEQUENCE:
f085be
+    case typelib_TypeClass_INTERFACE:
f085be
+        return RETURN_KIND_INDIRECT;
f085be
+    case typelib_TypeClass_STRUCT:
f085be
+        if (type->nSize > 16) {
f085be
+            return RETURN_KIND_INDIRECT;
f085be
+        }
f085be
+        switch (getStructKind(
f085be
+                    reinterpret_cast<typelib_CompoundTypeDescription const *>(
f085be
+                        type)))
f085be
+        {
f085be
+        case STRUCT_KIND_FLOAT:
f085be
+            return RETURN_KIND_HFA_FLOAT;
f085be
+        case STRUCT_KIND_DOUBLE:
f085be
+            return RETURN_KIND_HFA_DOUBLE;
f085be
+        case STRUCT_KIND_DTOR:
f085be
+            return RETURN_KIND_INDIRECT;
f085be
+        default:
f085be
+            return RETURN_KIND_REG;
f085be
+        }
f085be
+    }
f085be
+}
f085be
+
f085be
+}
f085be
+
f085be
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f085be
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
f085be
new file mode 100644
f085be
index 0000000..2e3ce61
f085be
--- /dev/null
f085be
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/abi.hxx
f085be
@@ -0,0 +1,87 @@
f085be
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
f085be
+/*
f085be
+ * This file is part of the LibreOffice project.
f085be
+ *
f085be
+ * This Source Code Form is subject to the terms of the Mozilla Public
f085be
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+ *
f085be
+ * This file incorporates work covered by the following license notice:
f085be
+ *
f085be
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
f085be
+ *   contributor license agreements. See the NOTICE file distributed
f085be
+ *   with this work for additional information regarding copyright
f085be
+ *   ownership. The ASF licenses this file to you under the Apache
f085be
+ *   License, Version 2.0 (the "License"); you may not use this file
f085be
+ *   except in compliance with the License. You may obtain a copy of
f085be
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
f085be
+ */
f085be
+
f085be
+#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_ABI_HXX
f085be
+#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_ABI_HXX
f085be
+
f085be
+#include <sal/config.h>
f085be
+
f085be
+#include <exception>
f085be
+#include <typeinfo>
f085be
+
f085be
+#include <typelib/typedescription.h>
f085be
+#include <uno/any2.h>
f085be
+#include <uno/mapping.h>
f085be
+
f085be
+namespace abi_aarch64 {
f085be
+
f085be
+// Following declarations from libstdc++-v3/libsupc++/unwind-cxx.h and
f085be
+// lib/gcc/*-*-*/*/include/unwind.h:
f085be
+
f085be
+struct _Unwind_Exception
f085be
+{
f085be
+    unsigned exception_class __attribute__((__mode__(__DI__)));
f085be
+    void * exception_cleanup;
f085be
+    unsigned private_1 __attribute__((__mode__(__word__)));
f085be
+    unsigned private_2 __attribute__((__mode__(__word__)));
f085be
+} __attribute__((__aligned__));
f085be
+
f085be
+struct __cxa_exception
f085be
+{
f085be
+    std::type_info *exceptionType;
f085be
+    void (*exceptionDestructor)(void *);
f085be
+
f085be
+    std::unexpected_handler unexpectedHandler;
f085be
+    std::terminate_handler terminateHandler;
f085be
+
f085be
+    __cxa_exception *nextException;
f085be
+
f085be
+    int handlerCount;
f085be
+
f085be
+    int handlerSwitchValue;
f085be
+    const unsigned char *actionRecord;
f085be
+    const unsigned char *languageSpecificData;
f085be
+    void *catchTemp;
f085be
+    void *adjustedPtr;
f085be
+
f085be
+    _Unwind_Exception unwindHeader;
f085be
+};
f085be
+
f085be
+struct __cxa_eh_globals
f085be
+{
f085be
+    __cxa_exception *caughtExceptions;
f085be
+    unsigned int uncaughtExceptions;
f085be
+};
f085be
+
f085be
+void mapException(
f085be
+    __cxa_exception * exception, uno_Any * any, uno_Mapping * mapping);
f085be
+
f085be
+void raiseException(uno_Any * any, uno_Mapping * mapping);
f085be
+
f085be
+enum ReturnKind {
f085be
+    RETURN_KIND_REG, RETURN_KIND_HFA_FLOAT, RETURN_KIND_HFA_DOUBLE,
f085be
+    RETURN_KIND_INDIRECT };
f085be
+
f085be
+ReturnKind getReturnKind(typelib_TypeDescription const * type);
f085be
+
f085be
+}
f085be
+
f085be
+#endif
f085be
+
f085be
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f085be
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx
f085be
new file mode 100644
f085be
index 0000000..09f7696
f085be
--- /dev/null
f085be
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.cxx
f085be
@@ -0,0 +1,66 @@
f085be
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
f085be
+/*
f085be
+ * This file is part of the LibreOffice project.
f085be
+ *
f085be
+ * This Source Code Form is subject to the terms of the Mozilla Public
f085be
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+ *
f085be
+ * This file incorporates work covered by the following license notice:
f085be
+ *
f085be
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
f085be
+ *   contributor license agreements. See the NOTICE file distributed
f085be
+ *   with this work for additional information regarding copyright
f085be
+ *   ownership. The ASF licenses this file to you under the Apache
f085be
+ *   License, Version 2.0 (the "License"); you may not use this file
f085be
+ *   except in compliance with the License. You may obtain a copy of
f085be
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
f085be
+ */
f085be
+
f085be
+#include <sal/config.h>
f085be
+
f085be
+#include <cstring>
f085be
+
f085be
+#include <sal/types.h>
f085be
+#include <sal/alloca.h>
f085be
+
f085be
+#include <callvirtualfunction.hxx>
f085be
+
f085be
+void callVirtualFunction(
f085be
+    unsigned long function, unsigned long * gpr, unsigned long * fpr,
f085be
+    unsigned long * stack, sal_Int32 sp, void * ret)
f085be
+{
f085be
+    void * stackargs;
f085be
+    if (sp != 0) {
f085be
+        stackargs = alloca(((sp + 1) >> 1) * 16);
f085be
+        std::memcpy(stackargs, stack, sp * 8);
f085be
+    }
f085be
+    asm volatile(
f085be
+        "ldp x0, x1, [%[gpr_]]\n\t"
f085be
+        "ldp x2, x3, [%[gpr_], #16]\n\t"
f085be
+        "ldp x4, x5, [%[gpr_], #32]\n\t"
f085be
+        "ldp x6, x7, [%[gpr_], #48]\n\t"
f085be
+        "ldr x8, %[ret_]\n\t"
f085be
+        "ldr x9, %[function_]\n\t"
f085be
+        "ldp d0, d1, [%[fpr_]]\n\t"
f085be
+        "ldp d2, d3, [%[fpr_], #16]\n\t"
f085be
+        "ldp d4, d5, [%[fpr_], #32]\n\t"
f085be
+        "ldp d6, d7, [%[fpr_], #48]\n\t"
f085be
+        "blr x9\n\t"
f085be
+        "stp x0, x1, [%[gpr_]]\n\t"
f085be
+        "stp d0, d1, [%[fpr_]]\n\t"
f085be
+        "stp d2, d3, [%[fpr_], #16]\n\t"
f085be
+        :: [gpr_]"r" (gpr), [fpr_]"r" (fpr), [function_]"m" (function),
f085be
+           [ret_]"m" (ret),
f085be
+           "m" (stackargs) // dummy input to prevent optimizing the alloca away
f085be
+        : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
f085be
+          "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18"/*TODO?*/, "v0",
f085be
+          "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
f085be
+          "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
f085be
+          "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
f085be
+          "memory"
f085be
+          // only the bottom 64 bits of v8--15 need to be preserved by callees
f085be
+    );
f085be
+}
f085be
+
f085be
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f085be
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx
f085be
new file mode 100644
f085be
index 0000000..b1b003f
f085be
--- /dev/null
f085be
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/callvirtualfunction.hxx
f085be
@@ -0,0 +1,33 @@
f085be
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
f085be
+/*
f085be
+ * This file is part of the LibreOffice project.
f085be
+ *
f085be
+ * This Source Code Form is subject to the terms of the Mozilla Public
f085be
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+ *
f085be
+ * This file incorporates work covered by the following license notice:
f085be
+ *
f085be
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
f085be
+ *   contributor license agreements. See the NOTICE file distributed
f085be
+ *   with this work for additional information regarding copyright
f085be
+ *   ownership. The ASF licenses this file to you under the Apache
f085be
+ *   License, Version 2.0 (the "License"); you may not use this file
f085be
+ *   except in compliance with the License. You may obtain a copy of
f085be
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
f085be
+ */
f085be
+
f085be
+#ifndef INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_CALLVIRTUALFUNCTION_HXX
f085be
+#define INCLUDED_BRIDGES_SOURCE_CPP_UNO_GCC3_LINUX_AARCH64_CALLVIRTUALFUNCTION_HXX
f085be
+
f085be
+#include <sal/config.h>
f085be
+
f085be
+#include <sal/types.h>
f085be
+
f085be
+void callVirtualFunction(
f085be
+    unsigned long function, unsigned long * gpr, unsigned long * fpr,
f085be
+    unsigned long * stack, sal_Int32 sp, void * ret);
f085be
+
f085be
+#endif
f085be
+
f085be
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f085be
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
f085be
new file mode 100644
f085be
index 0000000..a73d9be
f085be
--- /dev/null
f085be
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/cpp2uno.cxx
f085be
@@ -0,0 +1,464 @@
f085be
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
f085be
+/*
f085be
+ * This file is part of the LibreOffice project.
f085be
+ *
f085be
+ * This Source Code Form is subject to the terms of the Mozilla Public
f085be
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+ *
f085be
+ * This file incorporates work covered by the following license notice:
f085be
+ *
f085be
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
f085be
+ *   contributor license agreements. See the NOTICE file distributed
f085be
+ *   with this work for additional information regarding copyright
f085be
+ *   ownership. The ASF licenses this file to you under the Apache
f085be
+ *   License, Version 2.0 (the "License"); you may not use this file
f085be
+ *   except in compliance with the License. You may obtain a copy of
f085be
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
f085be
+ */
f085be
+
f085be
+#include <sal/config.h>
f085be
+
f085be
+#include <cassert>
f085be
+#include <cstdarg>
f085be
+#include <cstddef>
f085be
+#include <cstdlib>
f085be
+#include <cstring>
f085be
+
f085be
+#include <dlfcn.h>
f085be
+
f085be
+#include <com/sun/star/uno/XInterface.hpp>
f085be
+#include <com/sun/star/uno/genfunc.hxx>
f085be
+#include <sal/alloca.h>
f085be
+#include <sal/types.h>
f085be
+#include <typelib/typeclass.h>
f085be
+#include <typelib/typedescription.h>
f085be
+#include <typelib/typedescription.hxx>
f085be
+
f085be
+#include <bridges/cpp_uno/shared/bridge.hxx>
f085be
+#include <bridges/cpp_uno/shared/cppinterfaceproxy.hxx>
f085be
+#include <bridges/cpp_uno/shared/types.hxx>
f085be
+#include <bridges/cpp_uno/shared/vtablefactory.hxx>
f085be
+
f085be
+#include <abi.hxx>
f085be
+
f085be
+extern "C" void vtableSlotCall_();
f085be
+
f085be
+namespace {
f085be
+
f085be
+void call(
f085be
+    bridges::cpp_uno::shared::CppInterfaceProxy * proxy,
f085be
+    css::uno::TypeDescription const & description,
f085be
+    typelib_TypeDescriptionReference * returnType, sal_Int32 count,
f085be
+    typelib_MethodParameter * parameters, unsigned long * gpr,
f085be
+    unsigned long * fpr, unsigned long * stack, void * indirectRet)
f085be
+{
f085be
+    typelib_TypeDescription * rtd = 0;
f085be
+    if (returnType != 0) {
f085be
+        TYPELIB_DANGER_GET(&rtd, returnType);
f085be
+    }
f085be
+    abi_aarch64::ReturnKind retKind = rtd == 0
f085be
+        ? abi_aarch64::RETURN_KIND_REG : abi_aarch64::getReturnKind(rtd);
f085be
+    bool retConv = rtd != 0
f085be
+        && bridges::cpp_uno::shared::relatesToInterfaceType(rtd);
f085be
+    void * retin = retKind == abi_aarch64::RETURN_KIND_INDIRECT && !retConv
f085be
+        ? indirectRet : rtd == 0 ? 0 : alloca(rtd->nSize);
f085be
+    void ** args = static_cast< void ** >(alloca(count * sizeof (void *)));
f085be
+    void ** cppArgs = static_cast< void ** >(alloca(count * sizeof (void *)));
f085be
+    typelib_TypeDescription ** argtds = static_cast<typelib_TypeDescription **>(
f085be
+        alloca(count * sizeof (typelib_TypeDescription *)));
f085be
+    sal_Int32 ngpr = 1;
f085be
+    sal_Int32 nfpr = 0;
f085be
+    sal_Int32 sp = 0;
f085be
+    for (sal_Int32 i = 0; i != count; ++i) {
f085be
+        if (!parameters[i].bOut
f085be
+            && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
f085be
+        {
f085be
+            switch (parameters[i].pTypeRef->eTypeClass) {
f085be
+            case typelib_TypeClass_BOOLEAN:
f085be
+            case typelib_TypeClass_BYTE:
f085be
+            case typelib_TypeClass_SHORT:
f085be
+            case typelib_TypeClass_UNSIGNED_SHORT:
f085be
+            case typelib_TypeClass_LONG:
f085be
+            case typelib_TypeClass_UNSIGNED_LONG:
f085be
+            case typelib_TypeClass_HYPER:
f085be
+            case typelib_TypeClass_UNSIGNED_HYPER:
f085be
+            case typelib_TypeClass_CHAR:
f085be
+            case typelib_TypeClass_ENUM:
f085be
+                args[i] = ngpr == 8 ? stack + sp++ : gpr + ngpr++;
f085be
+                break;
f085be
+            case typelib_TypeClass_FLOAT:
f085be
+            case typelib_TypeClass_DOUBLE:
f085be
+                args[i] = nfpr == 8 ? stack + sp++ : fpr + nfpr++;
f085be
+                break;
f085be
+            default:
f085be
+                assert(false);
f085be
+            }
f085be
+            argtds[i] = 0;
f085be
+        } else {
f085be
+            cppArgs[i] = reinterpret_cast<void *>(
f085be
+                ngpr == 8 ? stack[sp++] : gpr[ngpr++]);
f085be
+            typelib_TypeDescription * ptd = 0;
f085be
+            TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
f085be
+            if (!parameters[i].bIn) {
f085be
+                args[i] = alloca(ptd->nSize);
f085be
+                argtds[i] = ptd;
f085be
+            } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) {
f085be
+                args[i] = alloca(ptd->nSize);
f085be
+                uno_copyAndConvertData(
f085be
+                    args[i], cppArgs[i], ptd, proxy->getBridge()->getCpp2Uno());
f085be
+                argtds[i] = ptd;
f085be
+            } else {
f085be
+                args[i] = cppArgs[i];
f085be
+                argtds[i] = 0;
f085be
+                TYPELIB_DANGER_RELEASE(ptd);
f085be
+            }
f085be
+        }
f085be
+    }
f085be
+    uno_Any exc;
f085be
+    uno_Any * pexc = &exc;
f085be
+    proxy->getUnoI()->pDispatcher(
f085be
+        proxy->getUnoI(), description.get(), retin, args, &pexc);
f085be
+    if (pexc != 0) {
f085be
+        for (sal_Int32 i = 0; i != count; ++i) {
f085be
+            if (argtds[i] != 0) {
f085be
+                if (parameters[i].bIn) {
f085be
+                    uno_destructData(args[i], argtds[i], 0);
f085be
+                }
f085be
+                TYPELIB_DANGER_RELEASE(argtds[i]);
f085be
+            }
f085be
+        }
f085be
+        if (rtd != 0) {
f085be
+            TYPELIB_DANGER_RELEASE(rtd);
f085be
+        }
f085be
+        abi_aarch64::raiseException(&exc, proxy->getBridge()->getUno2Cpp());
f085be
+    }
f085be
+    for (sal_Int32 i = 0; i != count; ++i) {
f085be
+        if (argtds[i] != 0) {
f085be
+            if (parameters[i].bOut) {
f085be
+                uno_destructData(
f085be
+                    cppArgs[i], argtds[i],
f085be
+                    reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
f085be
+                uno_copyAndConvertData(
f085be
+                    cppArgs[i], args[i], argtds[i],
f085be
+                    proxy->getBridge()->getUno2Cpp());
f085be
+            }
f085be
+            uno_destructData(args[i], argtds[i], 0);
f085be
+            TYPELIB_DANGER_RELEASE(argtds[i]);
f085be
+        }
f085be
+    }
f085be
+    void * retout = 0; // avoid false -Werror=maybe-uninitialized
f085be
+    switch (retKind) {
f085be
+    case abi_aarch64::RETURN_KIND_REG:
f085be
+        switch (rtd == 0 ? typelib_TypeClass_VOID : rtd->eTypeClass) {
f085be
+        case typelib_TypeClass_VOID:
f085be
+            break;
f085be
+        case typelib_TypeClass_BOOLEAN:
f085be
+        case typelib_TypeClass_BYTE:
f085be
+        case typelib_TypeClass_SHORT:
f085be
+        case typelib_TypeClass_UNSIGNED_SHORT:
f085be
+        case typelib_TypeClass_LONG:
f085be
+        case typelib_TypeClass_UNSIGNED_LONG:
f085be
+        case typelib_TypeClass_HYPER:
f085be
+        case typelib_TypeClass_UNSIGNED_HYPER:
f085be
+        case typelib_TypeClass_CHAR:
f085be
+        case typelib_TypeClass_ENUM:
f085be
+            std::memcpy(gpr, retin, rtd->nSize);
f085be
+            assert(!retConv);
f085be
+            break;
f085be
+        case typelib_TypeClass_FLOAT:
f085be
+        case typelib_TypeClass_DOUBLE:
f085be
+            std::memcpy(fpr, retin, rtd->nSize);
f085be
+            assert(!retConv);
f085be
+            break;
f085be
+        case typelib_TypeClass_STRUCT:
f085be
+            if (retConv) {
f085be
+                retout = gpr;
f085be
+            } else {
f085be
+                std::memcpy(gpr, retin, rtd->nSize);
f085be
+            }
f085be
+            break;
f085be
+        default:
f085be
+            assert(false);
f085be
+        }
f085be
+        break;
f085be
+    case abi_aarch64::RETURN_KIND_HFA_FLOAT:
f085be
+        assert(rtd != 0);
f085be
+        switch (rtd->nSize) {
f085be
+        case 16:
f085be
+            std::memcpy(fpr + 3, static_cast<char *>(retin) + 12, 4);
f085be
+            // fall through
f085be
+        case 12:
f085be
+            std::memcpy(fpr + 2, static_cast<char *>(retin) + 8, 4);
f085be
+            // fall through
f085be
+        case 8:
f085be
+            std::memcpy(fpr + 1, static_cast<char *>(retin) + 4, 4);
f085be
+            // fall through
f085be
+        case 4:
f085be
+            std::memcpy(fpr, retin, 4);
f085be
+            break;
f085be
+        default:
f085be
+            assert(false);
f085be
+        }
f085be
+        assert(!retConv);
f085be
+        break;
f085be
+    case abi_aarch64::RETURN_KIND_HFA_DOUBLE:
f085be
+        assert(rtd != 0);
f085be
+        std::memcpy(fpr, retin, rtd->nSize);
f085be
+        assert(!retConv);
f085be
+        break;
f085be
+    case abi_aarch64::RETURN_KIND_INDIRECT:
f085be
+        retout = indirectRet;
f085be
+        break;
f085be
+    }
f085be
+    if (retConv) {
f085be
+        uno_copyAndConvertData(
f085be
+            retout, retin, rtd, proxy->getBridge()->getUno2Cpp());
f085be
+        uno_destructData(retin, rtd, 0);
f085be
+    }
f085be
+    if (rtd != 0) {
f085be
+        TYPELIB_DANGER_RELEASE(rtd);
f085be
+    }
f085be
+}
f085be
+
f085be
+extern "C" void vtableCall(
f085be
+    sal_Int32 functionIndex, sal_Int32 vtableOffset,
f085be
+    unsigned long * gpr, unsigned long * fpr, unsigned long  * stack,
f085be
+    void * indirectRet)
f085be
+{
f085be
+    bridges::cpp_uno::shared::CppInterfaceProxy * proxy
f085be
+        = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
f085be
+            reinterpret_cast<char *>(gpr[0]) - vtableOffset);
f085be
+    typelib_InterfaceTypeDescription * type = proxy->getTypeDescr();
f085be
+    assert(functionIndex < type->nMapFunctionIndexToMemberIndex);
f085be
+    sal_Int32 pos = type->pMapFunctionIndexToMemberIndex[functionIndex];
f085be
+    css::uno::TypeDescription desc(type->ppAllMembers[pos]);
f085be
+    switch (desc.get()->eTypeClass) {
f085be
+    case typelib_TypeClass_INTERFACE_ATTRIBUTE:
f085be
+        if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) {
f085be
+            // Getter:
f085be
+            call(
f085be
+                proxy, desc,
f085be
+                reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(
f085be
+                    desc.get())->pAttributeTypeRef,
f085be
+                0, 0, gpr, fpr, stack, indirectRet);
f085be
+        } else {
f085be
+            // Setter:
f085be
+            typelib_MethodParameter param = {
f085be
+                0,
f085be
+                reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>(
f085be
+                    desc.get())->pAttributeTypeRef,
f085be
+                true, false };
f085be
+            call(proxy, desc, 0, 1, &param, gpr, fpr, stack, indirectRet);
f085be
+        }
f085be
+        break;
f085be
+    case typelib_TypeClass_INTERFACE_METHOD:
f085be
+        switch (functionIndex) {
f085be
+        case 1:
f085be
+            proxy->acquireProxy();
f085be
+            break;
f085be
+        case 2:
f085be
+            proxy->releaseProxy();
f085be
+            break;
f085be
+        case 0:
f085be
+            {
f085be
+                typelib_TypeDescription * td = 0;
f085be
+                TYPELIB_DANGER_GET(
f085be
+                    &td,
f085be
+                    (reinterpret_cast<css::uno::Type *>(gpr[1])
f085be
+                     ->getTypeLibType()));
f085be
+                if (td != 0 && td->eTypeClass == typelib_TypeClass_INTERFACE) {
f085be
+                    css::uno::XInterface * ifc = 0;
f085be
+                    proxy->getBridge()->getCppEnv()->getRegisteredInterface(
f085be
+                        proxy->getBridge()->getCppEnv(),
f085be
+                        reinterpret_cast<void **>(&ifc), proxy->getOid().pData,
f085be
+                        reinterpret_cast<typelib_InterfaceTypeDescription *>(
f085be
+                            td));
f085be
+                    if (ifc != 0) {
f085be
+                        uno_any_construct(
f085be
+                            reinterpret_cast<uno_Any *>(indirectRet), &ifc, td,
f085be
+                            reinterpret_cast<uno_AcquireFunc>(
f085be
+                                css::uno::cpp_acquire));
f085be
+                        ifc->release();
f085be
+                        TYPELIB_DANGER_RELEASE(td);
f085be
+                        break;
f085be
+                    }
f085be
+                    TYPELIB_DANGER_RELEASE(td);
f085be
+                }
f085be
+            }
f085be
+            // fall through
f085be
+        default:
f085be
+            call(
f085be
+                proxy, desc,
f085be
+                reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(
f085be
+                    desc.get())->pReturnTypeRef,
f085be
+                reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(
f085be
+                    desc.get())->nParams,
f085be
+                reinterpret_cast<typelib_InterfaceMethodTypeDescription *>(
f085be
+                    desc.get())->pParams,
f085be
+                gpr, fpr, stack, indirectRet);
f085be
+        }
f085be
+        break;
f085be
+    default:
f085be
+        assert(false);
f085be
+    }
f085be
+}
f085be
+
f085be
+struct aarch64_va_list {
f085be
+    void * stack;
f085be
+    void * gr_top;
f085be
+    void * vr_top;
f085be
+    int gr_offs;
f085be
+    int vr_offs;
f085be
+};
f085be
+
f085be
+#pragma GCC diagnostic push
f085be
+#pragma GCC diagnostic ignored "-Wvolatile-register-var"
f085be
+extern "C" void vtableSlotCall(
f085be
+    unsigned long gpr0, unsigned long gpr1, unsigned long gpr2,
f085be
+    unsigned long gpr3, unsigned long gpr4, unsigned long gpr5,
f085be
+    unsigned long gpr6, unsigned long gpr7, double fpr0, double fpr1,
f085be
+    double fpr2, double fpr3, double fpr4, double fpr5, double fpr6,
f085be
+    double fpr7, ...)
f085be
+{
f085be
+    register void * volatile indirectRet asm ("x8");
f085be
+    register sal_Int32 volatile functionIndex asm ("x9");
f085be
+    register sal_Int32 volatile vtableOffset asm ("x10");
f085be
+    va_list ap;
f085be
+    va_start(ap, fpr7);
f085be
+    assert(sizeof (va_list) == sizeof (aarch64_va_list));
f085be
+    unsigned long gpr[8];
f085be
+    gpr[0] = gpr0;
f085be
+    gpr[1] = gpr1;
f085be
+    gpr[2] = gpr2;
f085be
+    gpr[3] = gpr3;
f085be
+    gpr[4] = gpr4;
f085be
+    gpr[5] = gpr5;
f085be
+    gpr[6] = gpr6;
f085be
+    gpr[7] = gpr7;
f085be
+    double fpr[8];
f085be
+    fpr[0] = fpr0;
f085be
+    fpr[1] = fpr1;
f085be
+    fpr[2] = fpr2;
f085be
+    fpr[3] = fpr3;
f085be
+    fpr[4] = fpr4;
f085be
+    fpr[5] = fpr5;
f085be
+    fpr[6] = fpr6;
f085be
+    fpr[7] = fpr7;
f085be
+    vtableCall(
f085be
+        functionIndex, vtableOffset, gpr,
f085be
+        reinterpret_cast<unsigned long *>(fpr),
f085be
+        static_cast<unsigned long *>(
f085be
+            reinterpret_cast<aarch64_va_list *>(&ap)->stack),
f085be
+        indirectRet);
f085be
+    asm volatile(
f085be
+        "ldp x0, x1, [%[gpr_]]\n\t"
f085be
+        "ldp d0, d1, [%[fpr_]]\n\t"
f085be
+        "ldp d2, d3, [%[fpr_], #16]\n\t"
f085be
+        :: [gpr_]"r" (gpr), [fpr_]"r" (fpr)
f085be
+        : "r0", "r1", "v0", "v1", "v2", "v3");
f085be
+}
f085be
+#pragma GCC diagnostic pop
f085be
+
f085be
+std::size_t const codeSnippetSize = 8 * 4;
f085be
+
f085be
+unsigned char * generateCodeSnippet(
f085be
+    unsigned char * code, sal_Int32 functionIndex, sal_Int32 vtableOffset)
f085be
+{
f085be
+    // movz x9, <low functionIndex>
f085be
+    reinterpret_cast<unsigned int *>(code)[0] = 0xD2800009
f085be
+        | ((functionIndex & 0xFFFF) << 5);
f085be
+    // movk x9, <high functionIndex>, LSL #16
f085be
+    reinterpret_cast<unsigned int *>(code)[1] = 0xF2A00009
f085be
+        | ((functionIndex >> 16) << 5);
f085be
+    // movz x10, <low vtableOffset>
f085be
+    reinterpret_cast<unsigned int *>(code)[2] = 0xD280000A
f085be
+        | ((vtableOffset & 0xFFFF) << 5);
f085be
+    // movk x10, <high vtableOffset>, LSL #16
f085be
+    reinterpret_cast<unsigned int *>(code)[3] = 0xF2A0000A
f085be
+        | ((vtableOffset >> 16) << 5);
f085be
+    // ldr x11, +2*4
f085be
+    reinterpret_cast<unsigned int *>(code)[4] = 0x5800004B;
f085be
+    // br x11
f085be
+    reinterpret_cast<unsigned int *>(code)[5] = 0xD61F0160;
f085be
+    reinterpret_cast<unsigned long *>(code)[3]
f085be
+        = reinterpret_cast<unsigned long>(&vtableSlotCall);
f085be
+    return code + codeSnippetSize;
f085be
+}
f085be
+
f085be
+}
f085be
+
f085be
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
f085be
+
f085be
+bridges::cpp_uno::shared::VtableFactory::Slot *
f085be
+bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block) {
f085be
+    return static_cast<Slot *>(block) + 2;
f085be
+}
f085be
+
f085be
+sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
f085be
+    sal_Int32 slotCount)
f085be
+{
f085be
+    return (slotCount + 2) * sizeof (Slot) + slotCount * codeSnippetSize;
f085be
+}
f085be
+
f085be
+bridges::cpp_uno::shared::VtableFactory::Slot *
f085be
+bridges::cpp_uno::shared::VtableFactory::initializeBlock(
f085be
+    void * block, sal_Int32 slotCount)
f085be
+{
f085be
+    Slot * slots = mapBlockToVtable(block);
f085be
+    slots[-2].fn = 0;
f085be
+    slots[-1].fn = 0;
f085be
+    return slots + slotCount;
f085be
+}
f085be
+
f085be
+unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
f085be
+    Slot ** slots, unsigned char * code, sal_PtrDiff writetoexecdiff,
f085be
+    typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
f085be
+    sal_Int32 functionCount, sal_Int32 vtableOffset)
f085be
+{
f085be
+    (*slots) -= functionCount;
f085be
+    Slot * s = *slots;
f085be
+    for (sal_Int32 i = 0; i != type->nMembers; ++i) {
f085be
+        typelib_TypeDescription * td = 0;
f085be
+        TYPELIB_DANGER_GET(&td, type->ppMembers[i]);
f085be
+        assert(td != 0);
f085be
+        switch (td->eTypeClass) {
f085be
+        case typelib_TypeClass_INTERFACE_ATTRIBUTE:
f085be
+            {
f085be
+                typelib_InterfaceAttributeTypeDescription * atd
f085be
+                    = reinterpret_cast<
f085be
+                        typelib_InterfaceAttributeTypeDescription *>(td);
f085be
+                // Getter:
f085be
+                (s++)->fn = code + writetoexecdiff;
f085be
+                code = generateCodeSnippet(
f085be
+                    code, functionOffset++, vtableOffset);
f085be
+                // Setter:
f085be
+                if (!atd->bReadOnly) {
f085be
+                    (s++)->fn = code + writetoexecdiff;
f085be
+                    code = generateCodeSnippet(
f085be
+                        code, functionOffset++, vtableOffset);
f085be
+                }
f085be
+                break;
f085be
+            }
f085be
+        case typelib_TypeClass_INTERFACE_METHOD:
f085be
+            (s++)->fn = code + writetoexecdiff;
f085be
+            code = generateCodeSnippet(code, functionOffset++, vtableOffset);
f085be
+            break;
f085be
+        default:
f085be
+            assert(false);
f085be
+        }
f085be
+        TYPELIB_DANGER_RELEASE(td);
f085be
+    }
f085be
+    return code;
f085be
+}
f085be
+
f085be
+void bridges::cpp_uno::shared::VtableFactory::flushCode(
f085be
+    unsigned char const * begin, unsigned char const * end)
f085be
+{
f085be
+   static void (*clear_cache)(unsigned char const *, unsigned char const *)
f085be
+       = (void (*)(unsigned char const *, unsigned char const *)) dlsym(
f085be
+           RTLD_DEFAULT, "__clear_cache");
f085be
+   (*clear_cache)(begin, end);
f085be
+}
f085be
+
f085be
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f085be
diff --git a/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
f085be
new file mode 100644
f085be
index 0000000..9c9a24a
f085be
--- /dev/null
f085be
+++ b/bridges/source/cpp_uno/gcc3_linux_aarch64/uno2cpp.cxx
f085be
@@ -0,0 +1,376 @@
f085be
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
f085be
+/*
f085be
+ * This file is part of the LibreOffice project.
f085be
+ *
f085be
+ * This Source Code Form is subject to the terms of the Mozilla Public
f085be
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+ *
f085be
+ * This file incorporates work covered by the following license notice:
f085be
+ *
f085be
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
f085be
+ *   contributor license agreements. See the NOTICE file distributed
f085be
+ *   with this work for additional information regarding copyright
f085be
+ *   ownership. The ASF licenses this file to you under the Apache
f085be
+ *   License, Version 2.0 (the "License"); you may not use this file
f085be
+ *   except in compliance with the License. You may obtain a copy of
f085be
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
f085be
+ */
f085be
+
f085be
+#include <sal/config.h>
f085be
+
f085be
+#include <cassert>
f085be
+#include <cstring>
f085be
+#include <exception>
f085be
+#include <typeinfo>
f085be
+
f085be
+#include <cxxabi.h>
f085be
+
f085be
+#include <bridges/cpp_uno/shared/bridge.hxx>
f085be
+#include <bridges/cpp_uno/shared/types.hxx>
f085be
+#include <bridges/cpp_uno/shared/unointerfaceproxy.hxx>
f085be
+#include <bridges/cpp_uno/shared/vtables.hxx>
f085be
+#include <com/sun/star/uno/Exception.hpp>
f085be
+#include <com/sun/star/uno/RuntimeException.hpp>
f085be
+#include <com/sun/star/uno/genfunc.hxx>
f085be
+#include <rtl/textenc.h>
f085be
+#include <rtl/ustring.hxx>
f085be
+#include <sal/alloca.h>
f085be
+#include <sal/types.h>
f085be
+#include <typelib/typeclass.h>
f085be
+#include <typelib/typedescription.h>
f085be
+#include <uno/any2.h>
f085be
+#include <uno/data.h>
f085be
+
f085be
+#include <abi.hxx>
f085be
+#include <callvirtualfunction.hxx>
f085be
+
f085be
+namespace {
f085be
+
f085be
+void pushArgument(
f085be
+    unsigned long value, unsigned long * stack, sal_Int32 * sp,
f085be
+    unsigned long * regs, sal_Int32 * nregs)
f085be
+{
f085be
+    (*nregs != 8 ? regs[(*nregs)++] : stack[(*sp)++]) = value;
f085be
+}
f085be
+
f085be
+void call(
f085be
+    bridges::cpp_uno::shared::UnoInterfaceProxy * proxy,
f085be
+    bridges::cpp_uno::shared::VtableSlot slot,
f085be
+    typelib_TypeDescriptionReference * returnType, sal_Int32 count,
f085be
+    typelib_MethodParameter * parameters, void * returnValue, void ** arguments,
f085be
+    uno_Any ** exception)
f085be
+{
f085be
+    typelib_TypeDescription * rtd = 0;
f085be
+    TYPELIB_DANGER_GET(&rtd, returnType);
f085be
+    abi_aarch64::ReturnKind retKind = abi_aarch64::getReturnKind(rtd);
f085be
+    bool retConv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd);
f085be
+    void * ret = retConv ? alloca(rtd->nSize) : returnValue;
f085be
+    unsigned long ** thisPtr
f085be
+        = reinterpret_cast<unsigned long **>(proxy->getCppI()) + slot.offset;
f085be
+    unsigned long * stack = static_cast<unsigned long *>(
f085be
+        alloca(count * sizeof (unsigned long)));
f085be
+    sal_Int32 sp = 0;
f085be
+    unsigned long gpr[8];
f085be
+    sal_Int32 ngpr = 0;
f085be
+    unsigned long fpr[8];
f085be
+    sal_Int32 nfpr = 0;
f085be
+    gpr[ngpr++] = reinterpret_cast<unsigned long>(thisPtr);
f085be
+    void ** cppArgs = static_cast<void **>(alloca(count * sizeof (void *)));
f085be
+    typelib_TypeDescription ** ptds =
f085be
+        static_cast<typelib_TypeDescription **>(
f085be
+            alloca(count * sizeof (typelib_TypeDescription *)));
f085be
+    for (sal_Int32 i = 0; i != count; ++i) {
f085be
+        if (!parameters[i].bOut &&
f085be
+            bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
f085be
+        {
f085be
+            cppArgs[i] = 0;
f085be
+            switch (parameters[i].pTypeRef->eTypeClass) {
f085be
+            case typelib_TypeClass_BOOLEAN:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_Bool *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_BYTE:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_Int8 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_SHORT:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_Int16 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_UNSIGNED_SHORT:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_uInt16 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_LONG:
f085be
+            case typelib_TypeClass_ENUM:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_Int32 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_UNSIGNED_LONG:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_uInt32 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_HYPER:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_Int64 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_UNSIGNED_HYPER:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_uInt64 *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_FLOAT:
f085be
+                pushArgument(
f085be
+                    *static_cast<unsigned int *>(arguments[i]), stack, &sp, fpr,
f085be
+                    &nfpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_DOUBLE:
f085be
+                pushArgument(
f085be
+                    *static_cast<unsigned long *>(arguments[i]), stack, &sp,
f085be
+                    fpr, &nfpr);
f085be
+                break;
f085be
+            case typelib_TypeClass_CHAR:
f085be
+                pushArgument(
f085be
+                    *static_cast<sal_Unicode *>(arguments[i]), stack, &sp, gpr,
f085be
+                    &ngpr);
f085be
+                break;
f085be
+            default:
f085be
+                assert(false);
f085be
+            }
f085be
+        } else {
f085be
+            typelib_TypeDescription * ptd = 0;
f085be
+            TYPELIB_DANGER_GET(&ptd, parameters[i].pTypeRef);
f085be
+            if (!parameters[i].bIn) {
f085be
+                cppArgs[i] = alloca(ptd->nSize);
f085be
+                uno_constructData(cppArgs[i], ptd);
f085be
+                ptds[i] = ptd;
f085be
+                pushArgument(
f085be
+                    reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp,
f085be
+                    gpr, &ngpr);
f085be
+            } else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd)) {
f085be
+                cppArgs[i] = alloca(ptd->nSize);
f085be
+                uno_copyAndConvertData(
f085be
+                    cppArgs[i], arguments[i], ptd,
f085be
+                    proxy->getBridge()->getUno2Cpp());
f085be
+                ptds[i] = ptd;
f085be
+                pushArgument(
f085be
+                    reinterpret_cast<unsigned long>(cppArgs[i]), stack, &sp,
f085be
+                    gpr, &ngpr);
f085be
+            } else {
f085be
+                cppArgs[i] = 0;
f085be
+                pushArgument(
f085be
+                    reinterpret_cast<unsigned long>(arguments[i]), stack, &sp,
f085be
+                    gpr, &ngpr);
f085be
+                TYPELIB_DANGER_RELEASE(ptd);
f085be
+            }
f085be
+        }
f085be
+    }
f085be
+    try {
f085be
+        try {
f085be
+            callVirtualFunction(
f085be
+                (*thisPtr)[slot.index], gpr, fpr, stack, sp, ret);
f085be
+        } catch (css::uno::Exception &) {
f085be
+            throw;
f085be
+        } catch (std::exception & e) {
f085be
+            throw css::uno::RuntimeException(
f085be
+                ("C++ code threw "
f085be
+                 + OStringToOUString(typeid(e).name(), RTL_TEXTENCODING_UTF8)
f085be
+                 + ": " + OStringToOUString(e.what(), RTL_TEXTENCODING_UTF8)),
f085be
+                css::uno::Reference<css::uno::XInterface>());
f085be
+        } catch (...) {
f085be
+            throw css::uno::RuntimeException(
f085be
+                "C++ code threw unknown exception",
f085be
+                css::uno::Reference<css::uno::XInterface>());
f085be
+        }
f085be
+    } catch (css::uno::Exception &) {
f085be
+        abi_aarch64::mapException(
f085be
+            reinterpret_cast<abi_aarch64::__cxa_eh_globals *>(
f085be
+                __cxxabiv1::__cxa_get_globals())->caughtExceptions,
f085be
+            *exception, proxy->getBridge()->getCpp2Uno());
f085be
+        for (sal_Int32 i = 0; i != count; ++i) {
f085be
+            if (cppArgs[i] != 0) {
f085be
+                uno_destructData(
f085be
+                    cppArgs[i], ptds[i],
f085be
+                    reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
f085be
+                TYPELIB_DANGER_RELEASE(ptds[i]);
f085be
+            }
f085be
+        }
f085be
+        TYPELIB_DANGER_RELEASE(rtd);
f085be
+        return;
f085be
+    }
f085be
+    *exception = 0;
f085be
+    for (sal_Int32 i = 0; i != count; ++i) {
f085be
+        if (cppArgs[i] != 0) {
f085be
+            if (parameters[i].bOut) {
f085be
+                if (parameters[i].bIn) {
f085be
+                    uno_destructData(arguments[i], ptds[i], 0);
f085be
+                }
f085be
+                uno_copyAndConvertData(
f085be
+                    arguments[i], cppArgs[i], ptds[i],
f085be
+                    proxy->getBridge()->getCpp2Uno());
f085be
+            }
f085be
+            uno_destructData(
f085be
+                cppArgs[i], ptds[i],
f085be
+                reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
f085be
+            TYPELIB_DANGER_RELEASE(ptds[i]);
f085be
+        }
f085be
+    }
f085be
+    switch (retKind) {
f085be
+    case abi_aarch64::RETURN_KIND_REG:
f085be
+        switch (rtd->eTypeClass) {
f085be
+        case typelib_TypeClass_VOID:
f085be
+            break;
f085be
+        case typelib_TypeClass_BOOLEAN:
f085be
+        case typelib_TypeClass_BYTE:
f085be
+        case typelib_TypeClass_SHORT:
f085be
+        case typelib_TypeClass_UNSIGNED_SHORT:
f085be
+        case typelib_TypeClass_LONG:
f085be
+        case typelib_TypeClass_UNSIGNED_LONG:
f085be
+        case typelib_TypeClass_HYPER:
f085be
+        case typelib_TypeClass_UNSIGNED_HYPER:
f085be
+        case typelib_TypeClass_CHAR:
f085be
+        case typelib_TypeClass_ENUM:
f085be
+        case typelib_TypeClass_STRUCT:
f085be
+            std::memcpy(ret, gpr, rtd->nSize);
f085be
+            break;
f085be
+        case typelib_TypeClass_FLOAT:
f085be
+        case typelib_TypeClass_DOUBLE:
f085be
+            std::memcpy(ret, fpr, rtd->nSize);
f085be
+            break;
f085be
+        default:
f085be
+            assert(false);
f085be
+        }
f085be
+        break;
f085be
+    case abi_aarch64::RETURN_KIND_HFA_FLOAT:
f085be
+        switch (rtd->nSize) {
f085be
+        case 16:
f085be
+            std::memcpy(static_cast<char *>(ret) + 12, fpr + 3, 4);
f085be
+            // fall through
f085be
+        case 12:
f085be
+            std::memcpy(static_cast<char *>(ret) + 8, fpr + 2, 4);
f085be
+            // fall through
f085be
+        case 8:
f085be
+            std::memcpy(static_cast<char *>(ret) + 4, fpr + 1, 4);
f085be
+            // fall through
f085be
+        case 4:
f085be
+            std::memcpy(ret, fpr, 4);
f085be
+            break;
f085be
+        default:
f085be
+            assert(false);
f085be
+        }
f085be
+        break;
f085be
+    case abi_aarch64::RETURN_KIND_HFA_DOUBLE:
f085be
+        std::memcpy(ret, fpr, rtd->nSize);
f085be
+        break;
f085be
+    case abi_aarch64::RETURN_KIND_INDIRECT:
f085be
+        break;
f085be
+    }
f085be
+    if (retConv) {
f085be
+        uno_copyAndConvertData(
f085be
+            returnValue, ret, rtd, proxy->getBridge()->getCpp2Uno());
f085be
+        uno_destructData(
f085be
+            ret, rtd, reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
f085be
+    }
f085be
+    TYPELIB_DANGER_RELEASE(rtd);
f085be
+}
f085be
+
f085be
+}
f085be
+
f085be
+namespace bridges { namespace cpp_uno { namespace shared {
f085be
+
f085be
+void unoInterfaceProxyDispatch(
f085be
+    uno_Interface * pUnoI, typelib_TypeDescription const * pMemberDescr,
f085be
+    void * pReturn, void ** pArgs, uno_Any ** ppException)
f085be
+{
f085be
+    UnoInterfaceProxy * proxy = static_cast<UnoInterfaceProxy *>(pUnoI);
f085be
+    switch (pMemberDescr->eTypeClass) {
f085be
+    case typelib_TypeClass_INTERFACE_ATTRIBUTE:
f085be
+        {
f085be
+            typelib_InterfaceAttributeTypeDescription const * atd
f085be
+                = reinterpret_cast<
f085be
+                    typelib_InterfaceAttributeTypeDescription const *>(
f085be
+                        pMemberDescr);
f085be
+            VtableSlot slot(getVtableSlot(atd));
f085be
+            if (pReturn != 0) { // getter
f085be
+                call(
f085be
+                    proxy, slot, atd->pAttributeTypeRef, 0, 0, pReturn, pArgs,
f085be
+                    ppException);
f085be
+            } else { // setter
f085be
+                typelib_MethodParameter param = {
f085be
+                    0, atd->pAttributeTypeRef, true, false };
f085be
+                typelib_TypeDescriptionReference * rtd = 0;
f085be
+                typelib_typedescriptionreference_new(
f085be
+                    &rtd, typelib_TypeClass_VOID, OUString("void").pData);
f085be
+                slot.index += 1;
f085be
+                call(proxy, slot, rtd, 1, &param, pReturn, pArgs, ppException);
f085be
+                typelib_typedescriptionreference_release(rtd);
f085be
+            }
f085be
+            break;
f085be
+        }
f085be
+    case typelib_TypeClass_INTERFACE_METHOD:
f085be
+        {
f085be
+            typelib_InterfaceMethodTypeDescription const * mtd
f085be
+                = reinterpret_cast<
f085be
+                    typelib_InterfaceMethodTypeDescription const *>(
f085be
+                        pMemberDescr);
f085be
+            VtableSlot slot(getVtableSlot(mtd));
f085be
+            switch (slot.index) {
f085be
+            case 1:
f085be
+                pUnoI->acquire(pUnoI);
f085be
+                *ppException = 0;
f085be
+                break;
f085be
+            case 2:
f085be
+                pUnoI->release(pUnoI);
f085be
+                *ppException = 0;
f085be
+                break;
f085be
+            case 0:
f085be
+                {
f085be
+                    typelib_TypeDescription * td = 0;
f085be
+                    TYPELIB_DANGER_GET(
f085be
+                        &td,
f085be
+                        (reinterpret_cast<css::uno::Type *>(pArgs[0])
f085be
+                         ->getTypeLibType()));
f085be
+                    if (td != 0) {
f085be
+                        uno_Interface * ifc = 0;
f085be
+                        proxy->pBridge->getUnoEnv()->getRegisteredInterface(
f085be
+                            proxy->pBridge->getUnoEnv(),
f085be
+                            reinterpret_cast<void **>(&ifc), proxy->oid.pData,
f085be
+                            reinterpret_cast<
f085be
+                                typelib_InterfaceTypeDescription *>(td));
f085be
+                        if (ifc != 0) {
f085be
+                            uno_any_construct(
f085be
+                                reinterpret_cast<uno_Any *>(pReturn), &ifc, td,
f085be
+                                0);
f085be
+                            ifc->release(ifc);
f085be
+                            TYPELIB_DANGER_RELEASE(td);
f085be
+                            *ppException = 0;
f085be
+                            break;
f085be
+                        }
f085be
+                        TYPELIB_DANGER_RELEASE(td);
f085be
+                    }
f085be
+                }
f085be
+                // fall through
f085be
+            default:
f085be
+                call(
f085be
+                    proxy, slot, mtd->pReturnTypeRef, mtd->nParams,
f085be
+                    mtd->pParams, pReturn, pArgs, ppException);
f085be
+                break;
f085be
+            }
f085be
+            break;
f085be
+        }
f085be
+    default:
f085be
+        assert(false);
f085be
+    }
f085be
+}
f085be
+
f085be
+} } }
f085be
+
f085be
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f085be
diff --git a/configure.ac b/configure.ac
f085be
index 5ead2a0..826797f8 100644
f085be
--- a/configure.ac
f085be
+++ b/configure.ac
f085be
@@ -4292,6 +4292,12 @@ linux-gnu*)
f085be
 
f085be
     case "$host_cpu" in
f085be
 
f085be
+    aarch64)
f085be
+        CPUNAME=AARCH64
f085be
+        PLATFORMID=linux_aarch64
f085be
+        RTL_ARCH=AARCH64
f085be
+        OUTPATH=unxlngaarch64
f085be
+        ;;
f085be
     alpha)
f085be
         CPUNAME=AXP
f085be
         RTL_ARCH=ALPHA
f085be
diff --git a/desktop/source/deployment/misc/dp_platform.cxx b/desktop/source/deployment/misc/dp_platform.cxx
f085be
index 09b3fcd..6b04004 100644
f085be
--- a/desktop/source/deployment/misc/dp_platform.cxx
f085be
+++ b/desktop/source/deployment/misc/dp_platform.cxx
f085be
@@ -45,7 +45,7 @@
f085be
 #define PLATFORM_LINUX_S390x        "linux_s390x"
f085be
 #define PLATFORM_LINUX_HPPA         "linux_hppa"
f085be
 #define PLATFORM_LINUX_ALPHA        "linux_alpha"
f085be
-
f085be
+#define PLATFORM_LINUX_AARCH64      "linux_aarch64"
f085be
 
f085be
 
f085be
 #define PLATFORM_SOLARIS_SPARC      "solaris_sparc"
f085be
@@ -149,6 +149,8 @@ namespace
f085be
             ret = checkOSandCPU("Linux", "HPPA");
f085be
         else if (token == PLATFORM_LINUX_ALPHA)
f085be
             ret = checkOSandCPU("Linux", "ALPHA");
f085be
+        else if (token == PLATFORM_LINUX_AARCH64)
f085be
+            ret = checkOSandCPU("Linux", "AARCH64");
f085be
         else if (token == PLATFORM_SOLARIS_SPARC)
f085be
             ret = checkOSandCPU("Solaris", "SPARC");
f085be
         else if (token == PLATFORM_SOLARIS_SPARC64)
f085be
diff --git a/jvmfwk/plugins/sunmajor/pluginlib/vendorbase.hxx b/jvmfwk/plugins/sunmajor/pluginlib/vendorbase.hxx
f085be
index 25baaee5..29f2641 100644
f085be
--- a/jvmfwk/plugins/sunmajor/pluginlib/vendorbase.hxx
f085be
+++ b/jvmfwk/plugins/sunmajor/pluginlib/vendorbase.hxx
f085be
@@ -65,6 +65,8 @@ OpenJDK at least, but probably not true for Lemotes JDK */
f085be
 #define JFW_PLUGIN_ARCH "parisc"
f085be
 #elif defined AXP
f085be
 #define JFW_PLUGIN_ARCH "alpha"
f085be
+#elif defined AARCH64
f085be
+#define JFW_PLUGIN_ARCH "aarch64"
f085be
 #else // SPARC, INTEL, POWERPC, MIPS, ARM, IA64, M68K, HPPA, ALPHA
f085be
 #error unknown platform
f085be
 #endif // SPARC, INTEL, POWERPC, MIPS, ARM, IA64, M68K, HPPA, ALPHA
f085be
diff --git a/solenv/gbuild/platform/LINUX_AARCH64_GCC.mk b/solenv/gbuild/platform/LINUX_AARCH64_GCC.mk
f085be
new file mode 100644
f085be
index 0000000..682199e
f085be
--- /dev/null
f085be
+++ b/solenv/gbuild/platform/LINUX_AARCH64_GCC.mk
f085be
@@ -0,0 +1,14 @@
f085be
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
f085be
+#
f085be
+# This file is part of the LibreOffice project.
f085be
+#
f085be
+# This Source Code Form is subject to the terms of the Mozilla Public
f085be
+# License, v. 2.0. If a copy of the MPL was not distributed with this
f085be
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
f085be
+#
f085be
+
f085be
+gb_COMPILERDEFAULTOPTFLAGS := -Os
f085be
+
f085be
+include $(GBUILDDIR)/platform/linux.mk
f085be
+
f085be
+# vim: set noet sw=4:
f085be
-- 
f085be
1.9.3
f085be