<commit_before>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "applicationrunconfiguration.h"
#include "persistentsettings.h"
#include "environment.h"

#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>

#include <QtGui/QLabel>
#include <QtGui/QTextDocument>
#include <QDebug>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

/// ApplicationRunConfiguration

ApplicationRunConfiguration::ApplicationRunConfiguration(Project *pro)
    : RunConfiguration(pro)
{
}

ApplicationRunConfiguration::~ApplicationRunConfiguration()
{
}

QString ApplicationRunConfiguration::type() const
{
    return "ProjectExplorer.ApplicationRunConfiguration";
}

void ApplicationRunConfiguration::save(PersistentSettingsWriter &writer) const
{
    RunConfiguration::save(writer);
}

void ApplicationRunConfiguration::restore(const PersistentSettingsReader &reader)
{
    RunConfiguration::restore(reader);
}

/// ApplicationRunConfigurationRunner

ApplicationRunConfigurationRunner::ApplicationRunConfigurationRunner()
{
}

ApplicationRunConfigurationRunner::~ApplicationRunConfigurationRunner()
{
}

bool ApplicationRunConfigurationRunner::canRun(QSharedPointer<RunConfiguration> runConfiguration, const QString &mode)
{
    return (mode == ProjectExplorer::Constants::RUNMODE)
            && (!qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration).isNull());
}

QString ApplicationRunConfigurationRunner::displayName() const
{
    return QObject::tr("Run");
}

RunControl* ApplicationRunConfigurationRunner::run(QSharedPointer<RunConfiguration> runConfiguration, const QString &mode)
{
    QSharedPointer<ApplicationRunConfiguration> rc = qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration);
    Q_ASSERT(rc);
    Q_ASSERT(mode == ProjectExplorer::Constants::RUNMODE);

    ApplicationRunControl *runControl = new ApplicationRunControl(rc);
    return runControl;
}

QWidget *ApplicationRunConfigurationRunner::configurationWidget(QSharedPointer<RunConfiguration> runConfiguration)
{
    Q_UNUSED(runConfiguration);
    return new QLabel("TODO add Configuration widget");
}

// ApplicationRunControl

ApplicationRunControl::ApplicationRunControl(QSharedPointer<ApplicationRunConfiguration> runConfiguration)
    : RunControl(runConfiguration), m_applicationLauncher()
{
    connect(&m_applicationLauncher, SIGNAL(applicationError(QString)),
            this, SLOT(slotError(QString)));
    connect(&m_applicationLauncher, SIGNAL(appendOutput(QString)),
            this, SLOT(slotAddToOutputWindow(QString)));
    connect(&m_applicationLauncher, SIGNAL(processExited(int)),
            this, SLOT(processExited(int)));
    connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
            this, SLOT(bringApplicationToForeground(qint64)));
}

ApplicationRunControl::~ApplicationRunControl()
{
}

void ApplicationRunControl::start()
{
    QSharedPointer<ApplicationRunConfiguration> rc = qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration());
    Q_ASSERT(rc);

    m_applicationLauncher.setEnvironment(rc->environment().toStringList());
    m_applicationLauncher.setWorkingDirectory(rc->workingDirectory());

    m_executable = rc->executable();

    m_applicationLauncher.start(static_cast<Internal::ApplicationLauncher::Mode>(rc->runMode()),
                                m_executable, rc->commandLineArguments());
    emit started();

    emit addToOutputWindow(this, tr("Starting %1...").arg(m_executable));
}

void ApplicationRunControl::stop()
{
    m_applicationLauncher.stop();
}

bool ApplicationRunControl::isRunning() const
{
    return m_applicationLauncher.isRunning();
}

void ApplicationRunControl::slotError(const QString & err)
{
    emit error(this, err);
    emit finished();
}

void ApplicationRunControl::slotAddToOutputWindow(const QString &line)
{
    emit addToOutputWindowInline(this, line);
}

void ApplicationRunControl::processExited(int exitCode)
{
    emit addToOutputWindow(this, tr("%1 exited with code %2").arg(m_executable).arg(exitCode));
    emit finished();
}

<commit_msg>remove weird pointless initialization<commit_after>/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "applicationrunconfiguration.h"
#include "persistentsettings.h"
#include "environment.h"

#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>

#include <QtGui/QLabel>
#include <QtGui/QTextDocument>
#include <QDebug>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

/// ApplicationRunConfiguration

ApplicationRunConfiguration::ApplicationRunConfiguration(Project *pro)
    : RunConfiguration(pro)
{
}

ApplicationRunConfiguration::~ApplicationRunConfiguration()
{
}

QString ApplicationRunConfiguration::type() const
{
    return "ProjectExplorer.ApplicationRunConfiguration";
}

void ApplicationRunConfiguration::save(PersistentSettingsWriter &writer) const
{
    RunConfiguration::save(writer);
}

void ApplicationRunConfiguration::restore(const PersistentSettingsReader &reader)
{
    RunConfiguration::restore(reader);
}

/// ApplicationRunConfigurationRunner

ApplicationRunConfigurationRunner::ApplicationRunConfigurationRunner()
{
}

ApplicationRunConfigurationRunner::~ApplicationRunConfigurationRunner()
{
}

bool ApplicationRunConfigurationRunner::canRun(QSharedPointer<RunConfiguration> runConfiguration, const QString &mode)
{
    return (mode == ProjectExplorer::Constants::RUNMODE)
            && (!qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration).isNull());
}

QString ApplicationRunConfigurationRunner::displayName() const
{
    return QObject::tr("Run");
}

RunControl* ApplicationRunConfigurationRunner::run(QSharedPointer<RunConfiguration> runConfiguration, const QString &mode)
{
    QSharedPointer<ApplicationRunConfiguration> rc = qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration);
    Q_ASSERT(rc);
    Q_ASSERT(mode == ProjectExplorer::Constants::RUNMODE);

    ApplicationRunControl *runControl = new ApplicationRunControl(rc);
    return runControl;
}

QWidget *ApplicationRunConfigurationRunner::configurationWidget(QSharedPointer<RunConfiguration> runConfiguration)
{
    Q_UNUSED(runConfiguration);
    return new QLabel("TODO add Configuration widget");
}

// ApplicationRunControl

ApplicationRunControl::ApplicationRunControl(QSharedPointer<ApplicationRunConfiguration> runConfiguration)
    : RunControl(runConfiguration)
{
    connect(&m_applicationLauncher, SIGNAL(applicationError(QString)),
            this, SLOT(slotError(QString)));
    connect(&m_applicationLauncher, SIGNAL(appendOutput(QString)),
            this, SLOT(slotAddToOutputWindow(QString)));
    connect(&m_applicationLauncher, SIGNAL(processExited(int)),
            this, SLOT(processExited(int)));
    connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
            this, SLOT(bringApplicationToForeground(qint64)));
}

ApplicationRunControl::~ApplicationRunControl()
{
}

void ApplicationRunControl::start()
{
    QSharedPointer<ApplicationRunConfiguration> rc = qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration());
    Q_ASSERT(rc);

    m_applicationLauncher.setEnvironment(rc->environment().toStringList());
    m_applicationLauncher.setWorkingDirectory(rc->workingDirectory());

    m_executable = rc->executable();

    m_applicationLauncher.start(static_cast<Internal::ApplicationLauncher::Mode>(rc->runMode()),
                                m_executable, rc->commandLineArguments());
    emit started();

    emit addToOutputWindow(this, tr("Starting %1...").arg(m_executable));
}

void ApplicationRunControl::stop()
{
    m_applicationLauncher.stop();
}

bool ApplicationRunControl::isRunning() const
{
    return m_applicationLauncher.isRunning();
}

void ApplicationRunControl::slotError(const QString & err)
{
    emit error(this, err);
    emit finished();
}

void ApplicationRunControl::slotAddToOutputWindow(const QString &line)
{
    emit addToOutputWindowInline(this, line);
}

void ApplicationRunControl::processExited(int exitCode)
{
    emit addToOutputWindow(this, tr("%1 exited with code %2").arg(m_executable).arg(exitCode));
    emit finished();
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "desktopdevice.h"
#include "projectexplorerconstants.h"
#include "deviceprocesslist.h"
#include "localprocesslist.h"
#include "desktopdeviceconfigurationwidget.h"

#include <ssh/sshconnection.h>
#include <utils/portlist.h>

#include <QCoreApplication>

using namespace ProjectExplorer::Constants;

namespace ProjectExplorer {

DesktopDevice::DesktopDevice() : IDevice(Core::Id(DESKTOP_DEVICE_TYPE),
                                         IDevice::AutoDetected,
                                         IDevice::Hardware,
                                         Core::Id(DESKTOP_DEVICE_ID))
{
    setDisplayName(QCoreApplication::translate("ProjectExplorer::DesktopDevice", "Local PC"));
    setDeviceState(IDevice::DeviceStateUnknown);
    const QString portRange =
            QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END);
    setFreePorts(Utils::PortList::fromString(portRange));
}

DesktopDevice::DesktopDevice(const DesktopDevice &other) :
    IDevice(other)
{ }

IDevice::DeviceInfo DesktopDevice::deviceInformation() const
{
    return DeviceInfo();
}

QString DesktopDevice::displayType() const
{
    return QCoreApplication::translate("ProjectExplorer::DesktopDevice", "Desktop");
}

IDeviceWidget *DesktopDevice::createWidget()
{
    return new DesktopDeviceConfigurationWidget(sharedFromThis());
}

QList<Core::Id> DesktopDevice::actionIds() const
{
    return QList<Core::Id>();
}

QString DesktopDevice::displayNameForActionId(Core::Id actionId) const
{
    Q_UNUSED(actionId);
    return QString();
}

void DesktopDevice::executeAction(Core::Id actionId, QWidget *parent) const
{
    Q_UNUSED(actionId);
    Q_UNUSED(parent);
}

bool DesktopDevice::canAutoDetectPorts() const
{
    return true;
}

bool DesktopDevice::canCreateProcessModel() const
{
    return true;
}

DeviceProcessList *DesktopDevice::createProcessListModel(QObject *parent) const
{
    return new Internal::LocalProcessList(sharedFromThis(), parent);
}

IDevice::Ptr DesktopDevice::clone() const
{
    return Ptr(new DesktopDevice(*this));
}

} // namespace ProjectExplorer
<commit_msg>DesktopDevice: Hide Device Configuration widget<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "desktopdevice.h"
#include "projectexplorerconstants.h"
#include "deviceprocesslist.h"
#include "localprocesslist.h"
#include "desktopdeviceconfigurationwidget.h"

#include <ssh/sshconnection.h>
#include <utils/portlist.h>

#include <QCoreApplication>

using namespace ProjectExplorer::Constants;

namespace ProjectExplorer {

DesktopDevice::DesktopDevice() : IDevice(Core::Id(DESKTOP_DEVICE_TYPE),
                                         IDevice::AutoDetected,
                                         IDevice::Hardware,
                                         Core::Id(DESKTOP_DEVICE_ID))
{
    setDisplayName(QCoreApplication::translate("ProjectExplorer::DesktopDevice", "Local PC"));
    setDeviceState(IDevice::DeviceStateUnknown);
    const QString portRange =
            QString::fromLatin1("%1-%2").arg(DESKTOP_PORT_START).arg(DESKTOP_PORT_END);
    setFreePorts(Utils::PortList::fromString(portRange));
}

DesktopDevice::DesktopDevice(const DesktopDevice &other) :
    IDevice(other)
{ }

IDevice::DeviceInfo DesktopDevice::deviceInformation() const
{
    return DeviceInfo();
}

QString DesktopDevice::displayType() const
{
    return QCoreApplication::translate("ProjectExplorer::DesktopDevice", "Desktop");
}

IDeviceWidget *DesktopDevice::createWidget()
{
    return 0;
    // DesktopDeviceConfigurationWidget currently has just one editable field viz. free ports.
    // Querying for an available port is quite straightforward. Having a field for the port
    // range can be confusing to the user. Hence, disabling the widget for now.
}

QList<Core::Id> DesktopDevice::actionIds() const
{
    return QList<Core::Id>();
}

QString DesktopDevice::displayNameForActionId(Core::Id actionId) const
{
    Q_UNUSED(actionId);
    return QString();
}

void DesktopDevice::executeAction(Core::Id actionId, QWidget *parent) const
{
    Q_UNUSED(actionId);
    Q_UNUSED(parent);
}

bool DesktopDevice::canAutoDetectPorts() const
{
    return true;
}

bool DesktopDevice::canCreateProcessModel() const
{
    return true;
}

DeviceProcessList *DesktopDevice::createProcessListModel(QObject *parent) const
{
    return new Internal::LocalProcessList(sharedFromThis(), parent);
}

IDevice::Ptr DesktopDevice::clone() const
{
    return Ptr(new DesktopDevice(*this));
}

} // namespace ProjectExplorer
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmlchangeset.h"
#include "bindingproperty.h"
#include "variantproperty.h"
#include "qmlmodelview.h"
#include <metainfo.h>

namespace QmlDesigner {

ModelNode QmlModelStateOperation::target() const
{
    if (modelNode().property("target").isBindingProperty())
        return modelNode().bindingProperty("target").resolveToModelNode();
    else
        return ModelNode(); //exception?
}

void QmlModelStateOperation::setTarget(const ModelNode &target)
{
    modelNode().bindingProperty("target").setExpression(target.id());
}

bool QmlPropertyChanges::isValid() const
{
    return QmlModelNodeFacade::isValid() && modelNode().metaInfo().isSubclassOf("QtQuick.PropertyChanges", -1, -1);
}

bool QmlModelStateOperation::isValid() const
{
    return QmlModelNodeFacade::isValid() && (
                modelNode().metaInfo().isSubclassOf("<cpp>.QDeclarative1StateOperation", -1, -1)
                || modelNode().metaInfo().isSubclassOf("<cpp>.QDeclarativeStateOperation", -1, -1));
}

void QmlPropertyChanges::removeProperty(const QString &name)
{
    RewriterTransaction transaction(qmlModelView()->beginRewriterTransaction());
    if (name == "name")
        return;
    modelNode().removeProperty(name);
    if (modelNode().variantProperties().isEmpty() && modelNode().bindingProperties().count() < 2)
        modelNode().destroy();
}

} //QmlDesigner
<commit_msg>QmlDesigner.model: fix for state handling<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmlchangeset.h"
#include "bindingproperty.h"
#include "variantproperty.h"
#include "qmlmodelview.h"
#include <metainfo.h>

namespace QmlDesigner {

ModelNode QmlModelStateOperation::target() const
{
    if (modelNode().property("target").isBindingProperty())
        return modelNode().bindingProperty("target").resolveToModelNode();
    else
        return ModelNode(); //exception?
}

void QmlModelStateOperation::setTarget(const ModelNode &target)
{
    modelNode().bindingProperty("target").setExpression(target.id());
}

bool QmlPropertyChanges::isValid() const
{
    return QmlModelNodeFacade::isValid() && modelNode().metaInfo().isSubclassOf("QtQuick.PropertyChanges", -1, -1);
}

bool QmlModelStateOperation::isValid() const
{
    return QmlModelNodeFacade::isValid() && (
                modelNode().metaInfo().isSubclassOf("<cpp>.QDeclarative1StateOperation", -1, -1)
                || modelNode().metaInfo().isSubclassOf("<cpp>.QQuickStateOperation", -1, -1));
}

void QmlPropertyChanges::removeProperty(const QString &name)
{
    RewriterTransaction transaction(qmlModelView()->beginRewriterTransaction());
    if (name == "name")
        return;
    modelNode().removeProperty(name);
    if (modelNode().variantProperties().isEmpty() && modelNode().bindingProperties().count() < 2)
        modelNode().destroy();
}

} //QmlDesigner
<|endoftext|>


<commit_before>// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <stdio.h>
#include <stdlib.h>
#include <vespa/vespalib/net/socket_address.h>
#include <vespa/vespalib/stllike/string.h>
#include <set>

using vespalib::SocketAddress;

std::set<vespalib::string> make_ip_set() {
    std::set<vespalib::string> result;
    for (const auto &addr: SocketAddress::get_interfaces()) {
        result.insert(addr.ip_address());
    }
    return result;
}

vespalib::string get_hostname() {
    std::vector<char> result(4096, '\0');
    gethostname(&result[0], 4000);
    return SocketAddress::normalize(&result[0]);
}

bool check(const vespalib::string &name, const std::set<vespalib::string> &ip_set) {
    auto addr_list = SocketAddress::resolve(80, name.c_str());
    if (addr_list.empty()) {
        return false;
    }
    for (const SocketAddress &addr: addr_list) {
        vespalib::string ip_addr = addr.ip_address();
        if (ip_set.count(ip_addr) == 0) {
            return false;
        }
    }
    return true;
}

int main(int, char **) {
    auto my_ip_set = make_ip_set();
    std::vector<vespalib::string> list({get_hostname(), "localhost", "127.0.0.1", "::1"});
    for (const vespalib::string &name: list) {
        if (check(name, my_ip_set)) {
            fprintf(stdout, "%s\n", name.c_str());
            return 0;
        }
    }
    fprintf(stderr, "FATAL: hostname detection failed\n");
    // XXX we should explain why it failed
    return 1;
}
<commit_msg>fewer fallbacks and better error reporting<commit_after>// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <stdio.h>
#include <stdlib.h>
#include <vespa/vespalib/net/socket_address.h>
#include <vespa/vespalib/stllike/string.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <set>

using vespalib::SocketAddress;

std::set<vespalib::string> make_ip_set() {
    std::set<vespalib::string> result;
    for (const auto &addr: SocketAddress::get_interfaces()) {
        result.insert(addr.ip_address());
    }
    return result;
}

vespalib::string get_hostname() {
    std::vector<char> result(4096, '\0');
    gethostname(&result[0], 4000);
    return SocketAddress::normalize(&result[0]);
}

bool check(const vespalib::string &name, const std::set<vespalib::string> &ip_set, vespalib::string &error_msg) {
    auto addr_list = SocketAddress::resolve(80, name.c_str());
    if (addr_list.empty()) {
        error_msg = vespalib::make_string("hostname '%s' could not be resolved", name.c_str());
        return false;
    }
    for (const SocketAddress &addr: addr_list) {
        vespalib::string ip_addr = addr.ip_address();
        if (ip_set.count(ip_addr) == 0) {
            error_msg = vespalib::make_string("hostname '%s' resolves to ip address not owned by this host (%s)",
                                              name.c_str(), ip_addr.c_str());
            return false;
        }
    }
    return true;
}

int main(int, char **) {
    auto my_ip_set = make_ip_set();
    vespalib::string my_hostname = get_hostname();
    vespalib::string my_hostname_error;
    vespalib::string localhost = "localhost";
    vespalib::string localhost_error;
    if (check(my_hostname, my_ip_set, my_hostname_error)) {
        fprintf(stdout, "%s\n", my_hostname.c_str());
    } else if (check(localhost, my_ip_set, localhost_error)) {
        fprintf(stdout, "%s\n", localhost.c_str());
    } else {
        fprintf(stderr, "FATAL: hostname detection failed\n");
        fprintf(stderr, "  INFO: canonical hostname (from gethostname/getaddrinfo): %s\n", my_hostname.c_str());
        fprintf(stderr, "  ERROR: %s\n", my_hostname_error.c_str());
        fprintf(stderr, "  INFO: falling back to local hostname: %s\n", localhost.c_str());
        fprintf(stderr, "  ERROR: %s\n", localhost_error.c_str());
        return 1;
    }
    return 0;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenDqBitmap.C $     */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2013,2014              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/** @file  prdfCenDqBitmap.C */

#include <prdfCenDqBitmap.H>

#include <UtilHash.H>
#include <iipServiceDataCollector.h>

namespace PRDF
{

using namespace PlatServices;
using namespace fapi; // for spare dram config

bool CenDqBitmap::badDqs() const
{
    bool o_badDqs = false;

    for ( uint32_t i = 0; i < PORT_SLCT_PER_MBA; i++ )
    {
        for ( uint32_t j = 0; j < DIMM_DQ_RANK_BITMAP_SIZE; j++ )
        {
            if ( 0 != iv_data[i][j] )
            {
                o_badDqs = true;
                break;
            }
        }
        if ( o_badDqs ) break;
    }

    return o_badDqs;
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::badDqs( uint8_t i_portSlct, bool & o_badDqs ) const
{
    #define PRDF_FUNC "[CenDqBitmap::badDqs] "

    int32_t o_rc = SUCCESS;

    o_badDqs = false;

    do
    {
        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        for ( uint32_t j = 0; j < DIMM_DQ_RANK_BITMAP_SIZE; j++ )
        {
            if ( 0 != iv_data[i_portSlct][j] )
            {
                o_badDqs = true;
                break;
            }
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setDq( uint8_t i_dq, uint8_t i_portSlct )
{
    #define PRDF_FUNC "[CenDqBitmap::setDq] "

    int32_t o_rc = SUCCESS;

    do
    {
        if ( DQS_PER_DIMM <= i_dq )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_dq=%d", i_dq );
            o_rc = FAIL; break;
        }

        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = i_dq / DQS_PER_BYTE;
        uint8_t bitIdx  = i_dq % DQS_PER_BYTE;

        uint32_t shift = (DQS_PER_BYTE-1) - bitIdx; // 0-7
        iv_data[i_portSlct][byteIdx] |= 0x01 << shift;

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setSymbol( uint8_t i_symbol, uint8_t i_pins )
{
    #define PRDF_FUNC "[CenDqBitmap::setSymbol] "

    int32_t o_rc = SUCCESS;

    do
    {
        uint8_t evenDq   = CenSymbol::symbol2CenDq(    i_symbol );
        uint8_t portSlct = CenSymbol::symbol2PortSlct( i_symbol );
        if ( DQS_PER_DIMM <= evenDq || PORT_SLCT_PER_MBA <= portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_symbol=%d", i_symbol );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = evenDq / DQS_PER_BYTE;
        uint8_t bitIdx  = evenDq % DQS_PER_BYTE;

        i_pins &= 0x3; // limit to 2 bits
        uint32_t shift = (((DQS_PER_BYTE-1) - bitIdx) % 2) * 2; // 0,2,4,6
        iv_data[portSlct][byteIdx] |= i_pins << shift;

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setDram( uint8_t i_symbol, uint8_t i_pins )
{
    #define PRDF_FUNC "[CenDqBitmap::setDram] "

    int32_t o_rc = SUCCESS;

    do
    {
        uint8_t evenDq   = CenSymbol::symbol2CenDq(    i_symbol );
        uint8_t portSlct = CenSymbol::symbol2PortSlct( i_symbol );
        if ( DQS_PER_DIMM <= evenDq || PORT_SLCT_PER_MBA <= portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_symbol=%d", i_symbol );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = evenDq / DQS_PER_BYTE;
        uint8_t bitIdx  = evenDq % DQS_PER_BYTE;

        if ( isDramWidthX4(iv_mba) )
        {
            i_pins &= 0xf; // limit to 4 bits
            uint32_t shift = (((DQS_PER_BYTE-1) - bitIdx) % 4) * 4; // 0,4
            iv_data[portSlct][byteIdx] |= i_pins << shift;
        }
        else
        {
            i_pins &= 0xff; // limit to 8 bits
            iv_data[portSlct][byteIdx] |= i_pins;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::isChipMark( uint8_t i_symbol, bool & o_cm )
{
    #define PRDF_FUNC "[CenDqBitmap::isChipMark] "

    int32_t o_rc = SUCCESS;
    o_cm = false;

    do
    {
        uint8_t evenDq   = CenSymbol::symbol2CenDq(    i_symbol );
        uint8_t portSlct = CenSymbol::symbol2PortSlct( i_symbol );
        if ( DQS_PER_DIMM <= evenDq || PORT_SLCT_PER_MBA <= portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_symbol=%d", i_symbol );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = evenDq / DQS_PER_BYTE;
        uint8_t bitIdx  = evenDq % DQS_PER_BYTE;

        uint8_t pins   = 0xff;
        uint8_t cmData = iv_data[portSlct][byteIdx];

        if ( isDramWidthX4(iv_mba) )
        {
            pins = 0xf; // limit to 4 bits
            uint8_t shift = (((DQS_PER_BYTE-1) - bitIdx) % 4) * 4; // 0,4
            cmData = (cmData >> shift) & 0xf;
        }

        o_cm = ( cmData == pins );

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setDramSpare( uint8_t i_portSlct, uint8_t i_pins )
{
    #define PRDF_FUNC "[CenDqBitmap::setDramSpare] "

    int32_t o_rc = SUCCESS;

    do
    {
        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        uint8_t spareConfig = ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE;
        o_rc = getDimmSpareConfig( iv_mba , iv_rank, i_portSlct,
                                   spareConfig );
        if( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC"getDimmSpareConfig() failed" );
            o_rc = FAIL; break;
        }

        if ( ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE == spareConfig )
        {
            PRDF_ERR( PRDF_FUNC" Spare is not avaiable" );
            o_rc = FAIL; break;
        }

        if ( isDramWidthX4(iv_mba) )
        {
            i_pins &= 0xf; // limit to 4 bits

            if( ENUM_ATTR_EFF_DIMM_SPARE_LOW_NIBBLE  == spareConfig )
            {
                i_pins = i_pins << 4;
            }
            iv_data[i_portSlct][DIMM_DQ_RANK_BITMAP_SIZE-1] |= i_pins;
        }
        else
        {
            i_pins &= 0xff; // limit to 8 bits
            iv_data[i_portSlct][DIMM_DQ_RANK_BITMAP_SIZE-1] |= i_pins;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setEccSpare( uint8_t i_pins )
{

    #define PRDF_FUNC "[CenDqBitmap::setEccSpare] "

    int32_t o_rc = SUCCESS;

    do
    {
        if ( ! isDramWidthX4(iv_mba) )
        {
            PRDF_ERR( PRDF_FUNC"Invalid Call. Function called for MBA having "
                      "non X4 DRAM" );
            o_rc = FAIL; break;
        }
        // ECC spare bits are stored in port1, dq bits 68-71
        // Call setDram with symbol 0 to update the VPD for these bits.
        setDram( 0, i_pins );
    }while( 0 );

    return o_rc;
    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::isDramSpareAvailable( uint8_t i_portSlct,
                                           bool & o_available )
{
    #define PRDF_FUNC "[CenDqBitmap::isDramSpareAvailable] "

    int32_t o_rc = SUCCESS;

    o_available = false;

    do
    {
        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        uint8_t spareConfig = ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE;
        o_rc = getDimmSpareConfig( iv_mba , iv_rank, i_portSlct,
                                   spareConfig );
        if( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC"getDimmSpareConfig() failed" );
            break;
        }

        uint8_t spareDqBits = iv_data[i_portSlct][DIMM_DQ_RANK_BITMAP_SIZE-1];

        if ( isDramWidthX4(iv_mba) )
        {
            // Check for DRAM spare
            if( ENUM_ATTR_EFF_DIMM_SPARE_LOW_NIBBLE  == spareConfig )
            {
                o_available = ( 0 == ( spareDqBits & 0xf0 ) );
            }
            else if( ENUM_ATTR_EFF_DIMM_SPARE_HIGH_NIBBLE  == spareConfig )
            {
                o_available = ( 0 == ( spareDqBits & 0x0f ) );
            }

            if( false == o_available )
            {
                // check for ecc spare
                // ECC spare bits are stored in port1, dq bits 68-71
                // These bits map to symbol 0. Use isChipMark to check
                // if these bits are all 1.
                o_rc = isChipMark( 0, o_available );
                if( SUCCESS != o_rc )
                {
                    PRDF_ERR( PRDF_FUNC"isChipMark() failed" );
                    break;
                }
                // isChipMark return true if chip Mark is present.
                // Invert its value to get the right result.
                o_available = !(o_available);
            }
        }
        else
        {
            if ( ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE == spareConfig )
            {
                // spare is not available.
                o_available = false;
            }
            else
                o_available = ( 0 == spareDqBits );
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

void CenDqBitmap::getCaptureData( CaptureData & o_cd ) const
{
    uint8_t rank   = iv_rank.getMaster();
    size_t sz_rank = sizeof(rank);

    size_t sz_capData = sz_rank + sizeof(iv_data);

    // Adjust the size for endianess.
    const size_t sz_word = sizeof(CPU_WORD);
    sz_capData = ((sz_capData + sz_word-1) / sz_word) * sz_word;

    uint8_t capData[sz_capData];
    memset( capData, 0x00, sz_capData );

    capData[0] = rank;
    memcpy( &capData[1], iv_data, sizeof(iv_data) );

    // Fix endianess issues with non PPC machines.
    for ( uint32_t i = 0; i < (sz_capData/sz_word); i++ )
        ((CPU_WORD*)capData)[i] = htonl(((CPU_WORD*)capData)[i]);

    BIT_STRING_ADDRESS_CLASS bs ( 0, sz_capData*8, (CPU_WORD *) &capData );
    o_cd.Add( iv_mba, Util::hashString("BAD_DQ_BITMAP"), bs );
}

} // end namespace PRDF

<commit_msg>PRD: Fix in Vpd Update from Centaur DQ<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenDqBitmap.C $     */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2013,2014              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/** @file  prdfCenDqBitmap.C */

#include <prdfCenDqBitmap.H>

#include <UtilHash.H>
#include <iipServiceDataCollector.h>

namespace PRDF
{

using namespace PlatServices;
using namespace fapi; // for spare dram config

bool CenDqBitmap::badDqs() const
{
    bool o_badDqs = false;

    for ( uint32_t i = 0; i < PORT_SLCT_PER_MBA; i++ )
    {
        for ( uint32_t j = 0; j < DIMM_DQ_RANK_BITMAP_SIZE; j++ )
        {
            if ( 0 != iv_data[i][j] )
            {
                o_badDqs = true;
                break;
            }
        }
        if ( o_badDqs ) break;
    }

    return o_badDqs;
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::badDqs( uint8_t i_portSlct, bool & o_badDqs ) const
{
    #define PRDF_FUNC "[CenDqBitmap::badDqs] "

    int32_t o_rc = SUCCESS;

    o_badDqs = false;

    do
    {
        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        for ( uint32_t j = 0; j < DIMM_DQ_RANK_BITMAP_SIZE; j++ )
        {
            if ( 0 != iv_data[i_portSlct][j] )
            {
                o_badDqs = true;
                break;
            }
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setDq( uint8_t i_dq, uint8_t i_portSlct )
{
    #define PRDF_FUNC "[CenDqBitmap::setDq] "

    int32_t o_rc = SUCCESS;

    do
    {
        if ( DQS_PER_DIMM <= i_dq )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_dq=%d", i_dq );
            o_rc = FAIL; break;
        }

        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = i_dq / DQS_PER_BYTE;
        uint8_t bitIdx  = i_dq % DQS_PER_BYTE;

        uint32_t shift = (DQS_PER_BYTE-1) - bitIdx; // 0-7
        iv_data[i_portSlct][byteIdx] |= 0x01 << shift;

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setSymbol( uint8_t i_symbol, uint8_t i_pins )
{
    #define PRDF_FUNC "[CenDqBitmap::setSymbol] "

    int32_t o_rc = SUCCESS;

    do
    {
        uint8_t evenDq   = CenSymbol::symbol2CenDq(    i_symbol );
        uint8_t portSlct = CenSymbol::symbol2PortSlct( i_symbol );
        if ( DQS_PER_DIMM <= evenDq || PORT_SLCT_PER_MBA <= portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_symbol=%d", i_symbol );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = evenDq / DQS_PER_BYTE;
        uint8_t bitIdx  = evenDq % DQS_PER_BYTE;

        i_pins &= 0x3; // limit to 2 bits
        uint32_t shift = (((DQS_PER_BYTE-1) - bitIdx) / 2) * 2; // 0,2,4,6
        iv_data[portSlct][byteIdx] |= i_pins << shift;

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setDram( uint8_t i_symbol, uint8_t i_pins )
{
    #define PRDF_FUNC "[CenDqBitmap::setDram] "

    int32_t o_rc = SUCCESS;

    do
    {
        uint8_t evenDq   = CenSymbol::symbol2CenDq(    i_symbol );
        uint8_t portSlct = CenSymbol::symbol2PortSlct( i_symbol );
        if ( DQS_PER_DIMM <= evenDq || PORT_SLCT_PER_MBA <= portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_symbol=%d", i_symbol );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = evenDq / DQS_PER_BYTE;
        uint8_t bitIdx  = evenDq % DQS_PER_BYTE;

        if ( isDramWidthX4(iv_mba) )
        {
            i_pins &= 0xf; // limit to 4 bits
            uint32_t shift = (((DQS_PER_BYTE-1) - bitIdx) / 4) * 4; // 0,4
            iv_data[portSlct][byteIdx] |= i_pins << shift;
        }
        else
        {
            i_pins &= 0xff; // limit to 8 bits
            iv_data[portSlct][byteIdx] |= i_pins;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::isChipMark( uint8_t i_symbol, bool & o_cm )
{
    #define PRDF_FUNC "[CenDqBitmap::isChipMark] "

    int32_t o_rc = SUCCESS;
    o_cm = false;

    do
    {
        uint8_t evenDq   = CenSymbol::symbol2CenDq(    i_symbol );
        uint8_t portSlct = CenSymbol::symbol2PortSlct( i_symbol );
        if ( DQS_PER_DIMM <= evenDq || PORT_SLCT_PER_MBA <= portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_symbol=%d", i_symbol );
            o_rc = FAIL; break;
        }

        uint8_t byteIdx = evenDq / DQS_PER_BYTE;
        uint8_t bitIdx  = evenDq % DQS_PER_BYTE;

        uint8_t pins   = 0xff;
        uint8_t cmData = iv_data[portSlct][byteIdx];

        if ( isDramWidthX4(iv_mba) )
        {
            pins = 0xf; // limit to 4 bits
            uint8_t shift = (((DQS_PER_BYTE-1) - bitIdx) / 4) * 4; // 0,4
            cmData = (cmData >> shift) & 0xf;
        }

        o_cm = ( cmData == pins );

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setDramSpare( uint8_t i_portSlct, uint8_t i_pins )
{
    #define PRDF_FUNC "[CenDqBitmap::setDramSpare] "

    int32_t o_rc = SUCCESS;

    do
    {
        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        uint8_t spareConfig = ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE;
        o_rc = getDimmSpareConfig( iv_mba , iv_rank, i_portSlct,
                                   spareConfig );
        if( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC"getDimmSpareConfig() failed" );
            o_rc = FAIL; break;
        }

        if ( ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE == spareConfig )
        {
            PRDF_ERR( PRDF_FUNC" Spare is not avaiable" );
            o_rc = FAIL; break;
        }

        if ( isDramWidthX4(iv_mba) )
        {
            i_pins &= 0xf; // limit to 4 bits

            if( ENUM_ATTR_EFF_DIMM_SPARE_LOW_NIBBLE  == spareConfig )
            {
                i_pins = i_pins << 4;
            }
            iv_data[i_portSlct][DIMM_DQ_RANK_BITMAP_SIZE-1] |= i_pins;
        }
        else
        {
            i_pins &= 0xff; // limit to 8 bits
            iv_data[i_portSlct][DIMM_DQ_RANK_BITMAP_SIZE-1] |= i_pins;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::setEccSpare( uint8_t i_pins )
{

    #define PRDF_FUNC "[CenDqBitmap::setEccSpare] "

    int32_t o_rc = SUCCESS;

    do
    {
        if ( ! isDramWidthX4(iv_mba) )
        {
            PRDF_ERR( PRDF_FUNC"Invalid Call. Function called for MBA having "
                      "non X4 DRAM" );
            o_rc = FAIL; break;
        }
        // ECC spare bits are stored in port1, dq bits 68-71
        // Call setDram with symbol 0 to update the VPD for these bits.
        setDram( 0, i_pins );
    }while( 0 );

    return o_rc;
    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

int32_t CenDqBitmap::isDramSpareAvailable( uint8_t i_portSlct,
                                           bool & o_available )
{
    #define PRDF_FUNC "[CenDqBitmap::isDramSpareAvailable] "

    int32_t o_rc = SUCCESS;

    o_available = false;

    do
    {
        if ( PORT_SLCT_PER_MBA <= i_portSlct )
        {
            PRDF_ERR( PRDF_FUNC"Invalid parameter: i_portSlct=%d", i_portSlct );
            o_rc = FAIL; break;
        }

        uint8_t spareConfig = ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE;
        o_rc = getDimmSpareConfig( iv_mba , iv_rank, i_portSlct,
                                   spareConfig );
        if( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC"getDimmSpareConfig() failed" );
            break;
        }

        uint8_t spareDqBits = iv_data[i_portSlct][DIMM_DQ_RANK_BITMAP_SIZE-1];

        if ( isDramWidthX4(iv_mba) )
        {
            // Check for DRAM spare
            if( ENUM_ATTR_EFF_DIMM_SPARE_LOW_NIBBLE  == spareConfig )
            {
                o_available = ( 0 == ( spareDqBits & 0xf0 ) );
            }
            else if( ENUM_ATTR_EFF_DIMM_SPARE_HIGH_NIBBLE  == spareConfig )
            {
                o_available = ( 0 == ( spareDqBits & 0x0f ) );
            }

            if( false == o_available )
            {
                // check for ecc spare
                // ECC spare bits are stored in port1, dq bits 68-71
                // These bits map to symbol 0. Use isChipMark to check
                // if these bits are all 1.
                o_rc = isChipMark( 0, o_available );
                if( SUCCESS != o_rc )
                {
                    PRDF_ERR( PRDF_FUNC"isChipMark() failed" );
                    break;
                }
                // isChipMark return true if chip Mark is present.
                // Invert its value to get the right result.
                o_available = !(o_available);
            }
        }
        else
        {
            if ( ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE == spareConfig )
            {
                // spare is not available.
                o_available = false;
            }
            else
                o_available = ( 0 == spareDqBits );
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

void CenDqBitmap::getCaptureData( CaptureData & o_cd ) const
{
    uint8_t rank   = iv_rank.getMaster();
    size_t sz_rank = sizeof(rank);

    size_t sz_capData = sz_rank + sizeof(iv_data);

    // Adjust the size for endianess.
    const size_t sz_word = sizeof(CPU_WORD);
    sz_capData = ((sz_capData + sz_word-1) / sz_word) * sz_word;

    uint8_t capData[sz_capData];
    memset( capData, 0x00, sz_capData );

    capData[0] = rank;
    memcpy( &capData[1], iv_data, sizeof(iv_data) );

    // Fix endianess issues with non PPC machines.
    for ( uint32_t i = 0; i < (sz_capData/sz_word); i++ )
        ((CPU_WORD*)capData)[i] = htonl(((CPU_WORD*)capData)[i]);

    BIT_STRING_ADDRESS_CLASS bs ( 0, sz_capData*8, (CPU_WORD *) &capData );
    o_cd.Add( iv_mba, Util::hashString("BAD_DQ_BITMAP"), bs );
}

} // end namespace PRDF

<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
#include "MsgCatalogLoader.hpp"
#include "XMLMsgCat_Ids.hpp"

#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Public Constructors and Destructor
// ---------------------------------------------------------------------------
MsgCatalogLoader::MsgCatalogLoader(const XMLCh* const msgDomain)
:fCatalogHandle(0)
,fMsgSet(0)
{
    if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain)
    &&  !XMLString::equals(msgDomain, XMLUni::fgExceptDomain)
    &&  !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain)
    &&  !XMLString::equals(msgDomain, XMLUni::fgValidityDomain))
    {
        XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
    }

    // Prepare the path info
    char locationBuf[1024];
    memset(locationBuf, 0, sizeof locationBuf);
    const char *nlsHome = XMLMsgLoader::getNLSHome();

    if (nlsHome)
    {
    	strcpy(locationBuf, nlsHome);
        strcat(locationBuf, "/");
    }
    else
    {
        nlsHome = getenv("XERCESC_NLS_HOME");
        if (nlsHome)
        {
            strcpy(locationBuf, nlsHome);
            strcat(locationBuf, "/");
        }
        else
        {
            nlsHome = getenv("XERCESCROOT");
            if (nlsHome)
            {
                strcpy(locationBuf, nlsHome);
                strcat(locationBuf, "/msg/");
            }
        }
    }

    // Prepare user-specified locale specific cat file
    char catuser[1024];
    memset(catuser, 0, sizeof catuser);
    strcpy(catuser, locationBuf);
    strcat(catuser, "XercesMessages_");
    strcat(catuser, XMLMsgLoader::getLocale());
    strcat(catuser, ".cat");

    char catdefault[1024];
    memset(catdefault, 0, sizeof catdefault);
    strcpy(catdefault, locationBuf);
    strcat(catdefault, "XercesMessages_en_US.cat");

   /**
    * To open user-specified locale specific cat file
    * and default cat file if necessary
    */
    if ( ((int)(fCatalogHandle=catopen(catuser, 0)) == -1) &&
         ((int)(fCatalogHandle=catopen(catdefault, 0)) == -1)   )
    {
        // Probably have to call panic here
        printf("Could not open catalog:\n %s\n or %s\n", catuser, catdefault);
        XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
    }

    if (XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain))
        fMsgSet = CatId_XMLErrs;
    else if (XMLString::equals(msgDomain, XMLUni::fgExceptDomain))
        fMsgSet = CatId_XMLExcepts;
    else if (XMLString::equals(msgDomain, XMLUni::fgValidityDomain))
        fMsgSet = CatId_XMLValid;
    else if (XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain))
        fMsgSet = CatId_XMLDOMMsg;
}

MsgCatalogLoader::~MsgCatalogLoader()
{
    catclose(fCatalogHandle);
}

// ---------------------------------------------------------------------------
//  Implementation of the virtual message loader API
// ---------------------------------------------------------------------------
bool MsgCatalogLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
                              ,       XMLCh*   const          toFill
                              , const XMLSize_t               maxChars)
{
    char msgString[100];
    sprintf(msgString, "Could not find message ID %d from message set %d\n", msgToLoad, fMsgSet);
    char* catMessage = catgets( fCatalogHandle, fMsgSet, (int)msgToLoad, msgString);

    // catgets returns a pointer to msgString if it fails to locate the message
    // from the message catalog
    if (XMLString::equals(catMessage, msgString))
        return false;
    else
    {
        XMLString::transcode(catMessage, toFill, maxChars);
        return true;
    }

}

bool MsgCatalogLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const XMLSize_t               maxChars
                            , const XMLCh* const            repText1
                            , const XMLCh* const            repText2
                            , const XMLCh* const            repText3
                            , const XMLCh* const            repText4
                            , MemoryManager* const          manager)
{
    // Call the other version to load up the message
    if (!loadMsg(msgToLoad, toFill, maxChars))
        return false;

    // And do the token replacement
    XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
    return true;
}

bool MsgCatalogLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const XMLSize_t               maxChars
                            , const char* const             repText1
                            , const char* const             repText2
                            , const char* const             repText3
                            , const char* const             repText4
                            , MemoryManager * const         manager)
{
    //
    //  Transcode the provided parameters and call the other version,
    //  which will do the replacement work.
    //
    XMLCh* tmp1 = 0;
    XMLCh* tmp2 = 0;
    XMLCh* tmp3 = 0;
    XMLCh* tmp4 = 0;

    bool bRet = false;
    if (repText1)
        tmp1 = XMLString::transcode(repText1, manager);
    if (repText2)
        tmp2 = XMLString::transcode(repText2, manager);
    if (repText3)
        tmp3 = XMLString::transcode(repText3, manager);
    if (repText4)
        tmp4 = XMLString::transcode(repText4, manager);

    bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);

    if (tmp1)
        manager->deallocate(tmp1);//delete [] tmp1;
    if (tmp2)
        manager->deallocate(tmp2);//delete [] tmp2;
    if (tmp3)
        manager->deallocate(tmp3);//delete [] tmp3;
    if (tmp4)
        manager->deallocate(tmp4);//delete [] tmp4;

    return bRet;
}

XERCES_CPP_NAMESPACE_END
<commit_msg>Fixed 64 bit issue (XERCESC-1768)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
#include "MsgCatalogLoader.hpp"
#include "XMLMsgCat_Ids.hpp"

#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Public Constructors and Destructor
// ---------------------------------------------------------------------------
MsgCatalogLoader::MsgCatalogLoader(const XMLCh* const msgDomain)
:fCatalogHandle(0)
,fMsgSet(0)
{
    if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain)
    &&  !XMLString::equals(msgDomain, XMLUni::fgExceptDomain)
    &&  !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain)
    &&  !XMLString::equals(msgDomain, XMLUni::fgValidityDomain))
    {
        XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
    }

    // Prepare the path info
    char locationBuf[1024];
    memset(locationBuf, 0, sizeof locationBuf);
    const char *nlsHome = XMLMsgLoader::getNLSHome();

    if (nlsHome)
    {
    	strcpy(locationBuf, nlsHome);
        strcat(locationBuf, "/");
    }
    else
    {
        nlsHome = getenv("XERCESC_NLS_HOME");
        if (nlsHome)
        {
            strcpy(locationBuf, nlsHome);
            strcat(locationBuf, "/");
        }
        else
        {
            nlsHome = getenv("XERCESCROOT");
            if (nlsHome)
            {
                strcpy(locationBuf, nlsHome);
                strcat(locationBuf, "/msg/");
            }
        }
    }

    // Prepare user-specified locale specific cat file
    char catuser[1024];
    memset(catuser, 0, sizeof catuser);
    strcpy(catuser, locationBuf);
    strcat(catuser, "XercesMessages_");
    strcat(catuser, XMLMsgLoader::getLocale());
    strcat(catuser, ".cat");

    char catdefault[1024];
    memset(catdefault, 0, sizeof catdefault);
    strcpy(catdefault, locationBuf);
    strcat(catdefault, "XercesMessages_en_US.cat");

   /**
    * To open user-specified locale specific cat file
    * and default cat file if necessary
    */
    if ( ((fCatalogHandle=catopen(catuser, 0)) == (nl_catd)-1) &&
         ((fCatalogHandle=catopen(catdefault, 0)) == (nl_catd)-1)   )
    {
        // Probably have to call panic here
        printf("Could not open catalog:\n %s\n or %s\n", catuser, catdefault);
        XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
    }

    if (XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain))
        fMsgSet = CatId_XMLErrs;
    else if (XMLString::equals(msgDomain, XMLUni::fgExceptDomain))
        fMsgSet = CatId_XMLExcepts;
    else if (XMLString::equals(msgDomain, XMLUni::fgValidityDomain))
        fMsgSet = CatId_XMLValid;
    else if (XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain))
        fMsgSet = CatId_XMLDOMMsg;
}

MsgCatalogLoader::~MsgCatalogLoader()
{
    catclose(fCatalogHandle);
}

// ---------------------------------------------------------------------------
//  Implementation of the virtual message loader API
// ---------------------------------------------------------------------------
bool MsgCatalogLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
                              ,       XMLCh*   const          toFill
                              , const XMLSize_t               maxChars)
{
    char msgString[100];
    sprintf(msgString, "Could not find message ID %d from message set %d\n", msgToLoad, fMsgSet);
    char* catMessage = catgets( fCatalogHandle, fMsgSet, (int)msgToLoad, msgString);

    // catgets returns a pointer to msgString if it fails to locate the message
    // from the message catalog
    if (XMLString::equals(catMessage, msgString))
        return false;
    else
    {
        XMLString::transcode(catMessage, toFill, maxChars);
        return true;
    }

}

bool MsgCatalogLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const XMLSize_t               maxChars
                            , const XMLCh* const            repText1
                            , const XMLCh* const            repText2
                            , const XMLCh* const            repText3
                            , const XMLCh* const            repText4
                            , MemoryManager* const          manager)
{
    // Call the other version to load up the message
    if (!loadMsg(msgToLoad, toFill, maxChars))
        return false;

    // And do the token replacement
    XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
    return true;
}

bool MsgCatalogLoader::loadMsg(const  XMLMsgLoader::XMLMsgId  msgToLoad
                            ,       XMLCh* const            toFill
                            , const XMLSize_t               maxChars
                            , const char* const             repText1
                            , const char* const             repText2
                            , const char* const             repText3
                            , const char* const             repText4
                            , MemoryManager * const         manager)
{
    //
    //  Transcode the provided parameters and call the other version,
    //  which will do the replacement work.
    //
    XMLCh* tmp1 = 0;
    XMLCh* tmp2 = 0;
    XMLCh* tmp3 = 0;
    XMLCh* tmp4 = 0;

    bool bRet = false;
    if (repText1)
        tmp1 = XMLString::transcode(repText1, manager);
    if (repText2)
        tmp2 = XMLString::transcode(repText2, manager);
    if (repText3)
        tmp3 = XMLString::transcode(repText3, manager);
    if (repText4)
        tmp4 = XMLString::transcode(repText4, manager);

    bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);

    if (tmp1)
        manager->deallocate(tmp1);//delete [] tmp1;
    if (tmp2)
        manager->deallocate(tmp2);//delete [] tmp2;
    if (tmp3)
        manager->deallocate(tmp3);//delete [] tmp3;
    if (tmp4)
        manager->deallocate(tmp4);//delete [] tmp4;

    return bRet;
}

XERCES_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>//===- Symbols.cpp --------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Symbols.h"
#include "InputSection.h"
#include "Error.h"
#include "InputFiles.h"

#include "llvm/ADT/STLExtras.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf2;

static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
  if (VA == STV_DEFAULT)
    return VB;
  if (VB == STV_DEFAULT)
    return VA;
  return std::min(VA, VB);
}

// Returns 1, 0 or -1 if this symbol should take precedence
// over the Other, tie or lose, respectively.
template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
  assert(!isLazy() && !Other->isLazy());
  std::pair<bool, bool> L(isDefined(), !isWeak());
  std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());

  // Normalize
  if (L > R)
    return -Other->compare<ELFT>(this);

  Visibility = Other->Visibility =
      getMinVisibility(Visibility, Other->Visibility);

  if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
    IsUsedInRegularObj = Other->IsUsedInRegularObj = true;

  if (L != R)
    return -1;
  if (!L.first || !L.second)
    return 1;
  if (isShared())
    return -1;
  if (Other->isShared())
    return 1;
  if (isCommon()) {
    if (!Other->isCommon())
      return -1;
    auto *ThisC = cast<DefinedCommon<ELFT>>(this);
    auto *OtherC = cast<DefinedCommon<ELFT>>(Other);
    typename DefinedCommon<ELFT>::uintX_t MaxAlign =
        std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
    if (ThisC->Sym.st_size >= OtherC->Sym.st_size) {
      ThisC->MaxAlignment = MaxAlign;
      return 1;
    }
    OtherC->MaxAlignment = MaxAlign;
    return -1;
  }
  if (Other->isCommon())
    return 1;
  return 0;
}

std::unique_ptr<InputFile> Lazy::getMember() {
  MemoryBufferRef MBRef = File->getMember(&Sym);

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (MBRef.getBuffer().empty())
    return std::unique_ptr<InputFile>(nullptr);

  return createELFFile<ObjectFile>(MBRef);
}

template <class ELFT> static void doInitSymbols() {
  DefinedAbsolute<ELFT>::End.setBinding(STB_GLOBAL);
  DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
  DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
  Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);
}

void lld::elf2::initSymbols() {
  doInitSymbols<ELF32LE>();
  doInitSymbols<ELF32BE>();
  doInitSymbols<ELF64LE>();
  doInitSymbols<ELF64BE>();
}

template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
<commit_msg>Typedef uintX_t at beginning of a function just like others.<commit_after>//===- Symbols.cpp --------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Symbols.h"
#include "InputSection.h"
#include "Error.h"
#include "InputFiles.h"

#include "llvm/ADT/STLExtras.h"

using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;

using namespace lld;
using namespace lld::elf2;

static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
  if (VA == STV_DEFAULT)
    return VB;
  if (VB == STV_DEFAULT)
    return VA;
  return std::min(VA, VB);
}

// Returns 1, 0 or -1 if this symbol should take precedence
// over the Other, tie or lose, respectively.
template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
  typedef typename ELFFile<ELFT>::uintX_t uintX_t;
  assert(!isLazy() && !Other->isLazy());
  std::pair<bool, bool> L(isDefined(), !isWeak());
  std::pair<bool, bool> R(Other->isDefined(), !Other->isWeak());

  // Normalize
  if (L > R)
    return -Other->compare<ELFT>(this);

  Visibility = Other->Visibility =
      getMinVisibility(Visibility, Other->Visibility);

  if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
    IsUsedInRegularObj = Other->IsUsedInRegularObj = true;

  if (L != R)
    return -1;
  if (!L.first || !L.second)
    return 1;
  if (isShared())
    return -1;
  if (Other->isShared())
    return 1;
  if (isCommon()) {
    if (!Other->isCommon())
      return -1;
    auto *ThisC = cast<DefinedCommon<ELFT>>(this);
    auto *OtherC = cast<DefinedCommon<ELFT>>(Other);
    uintX_t Align = std::max(ThisC->MaxAlignment, OtherC->MaxAlignment);
    if (ThisC->Sym.st_size >= OtherC->Sym.st_size) {
      ThisC->MaxAlignment = Align;
      return 1;
    }
    OtherC->MaxAlignment = Align;
    return -1;
  }
  if (Other->isCommon())
    return 1;
  return 0;
}

std::unique_ptr<InputFile> Lazy::getMember() {
  MemoryBufferRef MBRef = File->getMember(&Sym);

  // getMember returns an empty buffer if the member was already
  // read from the library.
  if (MBRef.getBuffer().empty())
    return std::unique_ptr<InputFile>(nullptr);

  return createELFFile<ObjectFile>(MBRef);
}

template <class ELFT> static void doInitSymbols() {
  DefinedAbsolute<ELFT>::End.setBinding(STB_GLOBAL);
  DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
  DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
  Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);
}

void lld::elf2::initSymbols() {
  doInitSymbols<ELF32LE>();
  doInitSymbols<ELF32BE>();
  doInitSymbols<ELF64LE>();
  doInitSymbols<ELF64BE>();
}

template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
template int SymbolBody::compare<ELF64BE>(SymbolBody *Other);
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/cholesky_expander.h"

#include <memory>
#include <vector>

#include "tensorflow/compiler/xla/client/lib/arithmetic.h"
#include "tensorflow/compiler/xla/client/lib/constants.h"
#include "tensorflow/compiler/xla/client/lib/loops.h"
#include "tensorflow/compiler/xla/client/lib/math.h"
#include "tensorflow/compiler/xla/client/lib/matrix.h"
#include "tensorflow/compiler/xla/client/lib/slicing.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/literal.h"
#include "tensorflow/compiler/xla/primitive_util.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/status_macros.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/core/lib/core/errors.h"

namespace xla {

namespace {

// The Cholesky–Banachiewicz algorithm. See
// https://en.wikipedia.org/wiki/Cholesky_decomposition#The_Cholesky–Banachiewicz_and_Cholesky–Crout_algorithms
// for a description.
//
// def cholesky_unblocked(a):
//   assert len(a.shape) == 2 and a.shape[-2] == a.shape[-1]
//   n = a.shape[-2]
//   l = np.zeros_like(a)
//   for j in xrange(n):
//     row = l[..., j, :j]
//     row_t = np.swapaxes(row, -1, -2)
//     l[..., j, j] = np.sqrt(a[..., j, j] - np.dot(row, row_t))
//     l[..., j+1:, j] = (a[..., j+1:, j] - np.dot(l[..., j+1:, :j], row_t)) /
//                       l[..., j, j]
//   return l
// Returns a (result, error) pair.
std::pair<XlaOp, XlaOp> CholeskyUnblocked(
    XlaOp a, PrecisionConfig::Precision precision) {
  XlaBuilder* builder = a.builder();
  auto result = [&]() -> StatusOr<std::pair<XlaOp, XlaOp>> {
    TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a));
    const int n_dims = a_shape.rank();
    const int64 n = ShapeUtil::GetDimension(a_shape, -1);
    auto major_dims = AsInt64Slice(a_shape.dimensions())
                          .subspan(
                              /*pos=*/0,
                              /*len=*/n_dims - 2);

    XlaOp l = ZerosLike(a);

    // Construct the for loop body to iterate over rows.
    auto body_fn =
        [&](XlaOp i, absl::Span<const XlaOp> loop_vars,
            XlaBuilder* body_builder) -> StatusOr<std::vector<XlaOp>> {
      std::vector<int64> row_shape_dims(major_dims.begin(), major_dims.end());
      std::vector<int64> col_shape_dims(major_dims.begin(), major_dims.end());
      row_shape_dims.push_back(1);
      row_shape_dims.push_back(n);
      auto mask_zeros_row =
          Zeros(body_builder,
                ShapeUtil::MakeShape(a_shape.element_type(), row_shape_dims));

      col_shape_dims.push_back(n);
      col_shape_dims.push_back(1);
      auto mask_zeros_col =
          Zeros(body_builder,
                ShapeUtil::MakeShape(a_shape.element_type(), col_shape_dims));

      auto mask_range_row =
          Iota(body_builder, ShapeUtil::MakeShape(S32, row_shape_dims),
               /*iota_dimension=*/n_dims - 1);
      auto mask_range_col =
          Iota(body_builder, ShapeUtil::MakeShape(S32, col_shape_dims),
               /*iota_dimension=*/n_dims - 2);
      auto body_a = loop_vars[0];
      auto body_l = loop_vars[1];
      auto seen_error = loop_vars[2];

      // row = l[..., i, :i]
      // select the whole i-th row, then mask out all columns past i-1
      auto zero = ConstantR0<int32>(body_builder, 0);
      auto l_i = DynamicSliceInMinorDims(body_l, {i, zero}, {1, n});
      auto row = Select(Ge(mask_range_row, i), mask_zeros_row, l_i);
      // a[..., i, i]
      auto a_ii = DynamicSliceInMinorDims(body_a, {i, i}, {1, 1});
      // np.dot(row, np.swapaxes(row, -1, -2))
      auto diag_dot = BatchDot(row, false, row, true, precision);
      // l[..., i, i] = np.sqrt(a[..., i, i] - np.dot(row,
      //                                              np.swapaxes(row, -1, -2)))
      auto l_ii = a_ii - diag_dot;
      seen_error =
          Or(seen_error, Any(Or(Le(l_ii, ZerosLike(l_ii)), IsNan(l_ii))));
      l_ii = Sqrt(l_ii);

      // a[..., i+1:, i]
      // select the whole i-th column, then mask out all rows above i+1
      auto a_0i = DynamicSliceInMinorDims(body_a, {i}, {1});
      auto a_ip1i = Select(Le(mask_range_col, i), mask_zeros_col, a_0i);

      // l[..., i+1:, i] = (a[..., i+1:, i] - np.dot(l[..., i+1:, :i], r.T)) /
      //                   l[..., i, i]
      // The columns in [i, n] are zeroed out in `row`, so we just have to
      // zero out rows above i+1 after the BatchDot. np.dot(l[..., :, :i],
      // r.T)
      auto dot = BatchDot(body_l, false, row, true, precision);
      // np.dot(l[..., i+1:, :i], r.T)
      auto dot_ip1 = Select(Le(mask_range_col, i), mask_zeros_col, dot);

      body_l =
          DynamicUpdateSliceInMinorDims(body_l, (a_ip1i - dot_ip1) / l_ii, {i});
      // Assign the diagonal after the rest of the column because otherwise the
      // column assign will wrap around and overwrite the diagonal assign.
      body_l = DynamicUpdateSliceInMinorDims(body_l, l_ii, {i, i});

      return std::vector<XlaOp>{body_a, body_l, seen_error};
    };

    TF_ASSIGN_OR_RETURN(
        auto cholesky_while,
        ForEachIndex(n, S32, body_fn, {a, l, ConstantR0<bool>(builder, false)},
                     "unblocked", builder));

    return std::make_pair(cholesky_while[1], cholesky_while[2]);
  }();
  if (!result.ok()) {
    XlaOp error = builder->ReportError(result.status());
    return {error, error};
  }
  return result.ValueOrDie();
}

XlaOp BuildCholesky(XlaOp a, int64 block_size,
                    PrecisionConfig::Precision precision) {
  XlaBuilder* builder = a.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a));
    const int ndims = a_shape.rank();
    if (ndims < 2) {
      return InvalidArgument(
          "Argument to Cholesky must have rank >= 2; shape was %s",
          a_shape.ToString());
    }

    const int64 n = ShapeUtil::GetDimension(a_shape, -1);
    if (n != ShapeUtil::GetDimension(a_shape, -2)) {
      return InvalidArgument(
          "Argument to Cholesky must be batched square matrices; got shape %s",
          ShapeUtil::HumanString(a_shape));
    }

    if (primitive_util::IsComplexType(a_shape.element_type())) {
      return Unimplemented(
          "Complex types are not implemented in Cholesky; got shape %s",
          ShapeUtil::HumanString(a_shape));
    }

    if (block_size < 1) {
      return InvalidArgument(
          "block_size argument to Cholesky must be >= 1; got %d", block_size);
    }

    // Blocked left-looking Cholesky factorization.
    // Algorithm 1 from
    // Haidar, Azzam, et al. "High-performance Cholesky factorization for
    // GPU-only execution." Proceedings of General Purpose GPUs. ACM, 2017.
    XlaOp l = ZerosLike(a);
    XlaOp seen_error = ConstantR0<bool>(builder, false);
    for (int64 i = 0; i < n; i += block_size) {
      int64 k = std::min(block_size, n - i);
      if (i > 0) {
        // TODO(phawkins): consider implementing SYRK for the diagonal part of
        // the panel.
        // a[i:, i:i+k] -= np.dot(l[i:, :i], np.transpose(l[i:i+k, :i]))
        auto lhs = SliceInMinorDims(l, {i, 0}, {n, i});
        auto rhs = SliceInMinorDims(l, {i, 0}, {i + k, i});
        auto delta = BatchDot(lhs, false, rhs, true, precision);
        auto before = SliceInMinorDims(a, {i, i}, {n, i + k});
        a = UpdateSliceInMinorDims(a, before - delta, {i, i});
      }

      // l[i:i+k, i:i+k] = cholesky_unblocked(a[i:i+k, i:i+k])
      auto x = SliceInMinorDims(a, {i, i}, {i + k, i + k});
      XlaOp factorized;
      XlaOp factorized_error;
      std::tie(factorized, factorized_error) = CholeskyUnblocked(x, precision);
      seen_error = Or(seen_error, factorized_error);
      l = UpdateSliceInMinorDims(l, factorized, {i, i});

      if (i + k < n) {
        // l[i+k:, i:i+k] =
        //     trsm_right_transpose(l[i:i+k, i:i+k], a[i+k:, i:i+k])
        auto panel = SliceInMinorDims(a, {i + k, i}, {n, i + k});
        auto update =
            TriangularSolve(factorized, panel,
                            /*left_side=*/false,
                            /*lower=*/true,
                            /*unit_diagonal=*/false,
                            /*transpose_a=*/TriangularSolveOptions::TRANSPOSE);
        l = UpdateSliceInMinorDims(l, update, {i + k, i});
      }
    }
    return Select(seen_error,
                  FullLike(l, std::numeric_limits<float>::quiet_NaN()), l);
  });
}

}  // namespace

bool CholeskyExpander::InstructionMatchesPattern(HloInstruction* instruction) {
  return instruction->opcode() == HloOpcode::kCholesky;
}

StatusOr<HloInstruction*> CholeskyExpander::ExpandInstruction(
    HloInstruction* instruction) {
  const CholeskyOptions& options = instruction->cholesky_options();
  const string name = absl::StrFormat(
      "xla.cholesky_%s_%s", instruction->operand(0)->shape().ToString(),
      options.lower() ? "lower" : "upper");

  HloModule* module = instruction->parent()->parent();

  HloComputation*& computation =
      computation_cache_.emplace(name, nullptr).first->second;
  if (!computation) {
    // Builds a new expansion.
    //
    // TODO(b/62327888): We do something unusual here: we build the computation
    // using the XlaBuilder API, which is nominally an XLA client API. We do
    // this because the external APIs for building complicated computations
    // (XlaBuilder) are much more ergonomic than the internal ones. As it turns
    // out, XlaBuilder isn't really a client API—what it does is build a
    // HloModuleProto protocol buffer, that we can then deserialize and clone
    // into our HloModule. Ideally we would avoid the protocol buffer step;
    // that is left as an exercise for future work.
    XlaBuilder builder(name);
    XlaOp a = Parameter(&builder, 0, instruction->operand(0)->shape(), "a");
    XlaOp l = BuildCholesky(MaybeTransposeInMinorDims(a, !options.lower()),
                            /*block_size=*/128,
                            /*precision=*/PrecisionConfig::HIGHEST);
    MaybeTransposeInMinorDims(l, !options.lower());

    TF_ASSIGN_OR_RETURN(XlaComputation xla_computation, builder.Build());

    TF_ASSIGN_OR_RETURN(ProgramShape program_shape,
                        xla_computation.GetProgramShape());
    HloModuleConfig config(program_shape);
    TF_ASSIGN_OR_RETURN(auto new_module, HloModule::CreateFromProto(
                                             xla_computation.proto(), config));
    HloCloneContext context(module);
    computation =
        module->DeepCloneComputation(new_module->entry_computation(), &context);
  }

  return instruction->parent()->AddInstruction(HloInstruction::CreateCall(
      instruction->shape(), instruction->operands(), computation));
}

}  // namespace xla
<commit_msg>Cholesky decomposition optimization. Use matmul and mask to replace slice and dynamic update slice.<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/service/cholesky_expander.h"

#include <memory>
#include <vector>

#include "tensorflow/compiler/xla/client/lib/arithmetic.h"
#include "tensorflow/compiler/xla/client/lib/constants.h"
#include "tensorflow/compiler/xla/client/lib/loops.h"
#include "tensorflow/compiler/xla/client/lib/math.h"
#include "tensorflow/compiler/xla/client/lib/matrix.h"
#include "tensorflow/compiler/xla/client/lib/slicing.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/literal.h"
#include "tensorflow/compiler/xla/primitive_util.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/status_macros.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/core/lib/core/errors.h"

namespace xla {

namespace {

// The Cholesky–Banachiewicz algorithm. See
// https://en.wikipedia.org/wiki/Cholesky_decomposition#The_Cholesky–Banachiewicz_and_Cholesky–Crout_algorithms
// for a description.
//
// def cholesky_unblocked(a):
//   assert len(a.shape) == 2 and a.shape[-2] == a.shape[-1]
//   n = a.shape[-2]
//   l = np.zeros_like(a)
//   for j in xrange(n):
//     mask = np.zeros_like(a)
//     mask[i, k] == 1 when i >= k and k == j
//     l_square = np.dot(l, l_t)
//     temp = a - l_square
//     l[..., j, j] = temp(j, j)
//     l = temp / l[..., j, j) * mask + l
//   return l
// Returns a (result, error) pair.
std::pair<XlaOp, XlaOp> CholeskyUnblocked(
    XlaOp a, PrecisionConfig::Precision precision) {
  XlaBuilder* builder = a.builder();
  auto result = [&]() -> StatusOr<std::pair<XlaOp, XlaOp>> {
    TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a));
    const int n_dims = a_shape.rank();
    const int64 n = ShapeUtil::GetDimension(a_shape, -1);
    auto major_dims = AsInt64Slice(a_shape.dimensions())
                          .subspan(
                              /*pos=*/0,
                              /*len=*/n_dims - 2);

    auto matrix_dims = AsInt64Slice(a_shape.dimensions())
                           .subspan(
                               /*pos=*/0,
                               /*len=*/n_dims);

    XlaOp l = ZerosLike(a);

    // Construct the for loop body to iterate over rows.
    auto body_fn =
        [&](XlaOp i, absl::Span<const XlaOp> loop_vars,
            XlaBuilder* body_builder) -> StatusOr<std::vector<XlaOp>> {
      std::vector<int64> row_shape_dims(major_dims.begin(), major_dims.end());
      std::vector<int64> col_shape_dims(major_dims.begin(), major_dims.end());
      auto body_a = loop_vars[0];
      auto body_l = loop_vars[1];
      auto seen_error = loop_vars[2];
      auto iota_row = Iota(body_builder, ShapeUtil::MakeShape(S32, matrix_dims),
                           n_dims - 1);
      auto iota_col = Iota(body_builder, ShapeUtil::MakeShape(S32, matrix_dims),
                           n_dims - 2);

      auto mask_pred = Ge(iota_col, iota_row);
      mask_pred = And(mask_pred, Eq(iota_row, i));
      auto mask_zeros =
          Zeros(body_builder,
                ShapeUtil::MakeShape(a_shape.element_type(), matrix_dims));
      // L * L.T, This matrix has of a lot of multiplying with zero
      // (namely, L[:, j:] = 0) and redudant computation, but it is faster
      // than slice.
      auto l_square = BatchDot(body_l, false, body_l, true, precision);

      // A - L*L.T
      l_square = body_a - l_square;
      auto l_ii = DynamicSliceInMinorDims(l_square, {i, i}, {1, 1});
      l_ii = Sqrt(l_ii);
      // L = (A - L*L.T) / l_ii * mask + L
      body_l = Select(mask_pred, l_square / l_ii, mask_zeros) + body_l;

      seen_error =
          Or(seen_error, Any(Or(Le(l_ii, ZerosLike(l_ii)), IsNan(l_ii))));

      return std::vector<XlaOp>{body_a, body_l, seen_error};
    };

    TF_ASSIGN_OR_RETURN(
        auto cholesky_while,
        ForEachIndex(n, S32, body_fn, {a, l, ConstantR0<bool>(builder, false)},
                     "unblocked", builder));

    return std::make_pair(cholesky_while[1], cholesky_while[2]);
  }();
  if (!result.ok()) {
    XlaOp error = builder->ReportError(result.status());
    return {error, error};
  }
  return result.ValueOrDie();
}

XlaOp BuildCholesky(XlaOp a, int64 block_size,
                    PrecisionConfig::Precision precision) {
  XlaBuilder* builder = a.builder();
  return builder->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> {
    TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a));
    const int ndims = a_shape.rank();
    if (ndims < 2) {
      return InvalidArgument(
          "Argument to Cholesky must have rank >= 2; shape was %s",
          a_shape.ToString());
    }

    const int64 n = ShapeUtil::GetDimension(a_shape, -1);
    if (n != ShapeUtil::GetDimension(a_shape, -2)) {
      return InvalidArgument(
          "Argument to Cholesky must be batched square matrices; got shape %s",
          ShapeUtil::HumanString(a_shape));
    }

    if (primitive_util::IsComplexType(a_shape.element_type())) {
      return Unimplemented(
          "Complex types are not implemented in Cholesky; got shape %s",
          ShapeUtil::HumanString(a_shape));
    }

    if (block_size < 1) {
      return InvalidArgument(
          "block_size argument to Cholesky must be >= 1; got %d", block_size);
    }

    // Blocked left-looking Cholesky factorization.
    // Algorithm 1 from
    // Haidar, Azzam, et al. "High-performance Cholesky factorization for
    // GPU-only execution." Proceedings of General Purpose GPUs. ACM, 2017.
    XlaOp l = ZerosLike(a);
    XlaOp seen_error = ConstantR0<bool>(builder, false);
    for (int64 i = 0; i < n; i += block_size) {
      int64 k = std::min(block_size, n - i);
      if (i > 0) {
        // TODO(phawkins): consider implementing SYRK for the diagonal part of
        // the panel.
        // a[i:, i:i+k] -= np.dot(l[i:, :i], np.transpose(l[i:i+k, :i]))
        auto lhs = SliceInMinorDims(l, {i, 0}, {n, i});
        auto rhs = SliceInMinorDims(l, {i, 0}, {i + k, i});
        auto delta = BatchDot(lhs, false, rhs, true, precision);
        auto before = SliceInMinorDims(a, {i, i}, {n, i + k});
        a = UpdateSliceInMinorDims(a, before - delta, {i, i});
      }

      // l[i:i+k, i:i+k] = cholesky_unblocked(a[i:i+k, i:i+k])
      auto x = SliceInMinorDims(a, {i, i}, {i + k, i + k});
      XlaOp factorized;
      XlaOp factorized_error;
      std::tie(factorized, factorized_error) = CholeskyUnblocked(x, precision);
      seen_error = Or(seen_error, factorized_error);
      l = UpdateSliceInMinorDims(l, factorized, {i, i});

      if (i + k < n) {
        // l[i+k:, i:i+k] =
        //     trsm_right_transpose(l[i:i+k, i:i+k], a[i+k:, i:i+k])
        auto panel = SliceInMinorDims(a, {i + k, i}, {n, i + k});
        auto update =
            TriangularSolve(factorized, panel,
                            /*left_side=*/false,
                            /*lower=*/true,
                            /*unit_diagonal=*/false,
                            /*transpose_a=*/TriangularSolveOptions::TRANSPOSE);
        l = UpdateSliceInMinorDims(l, update, {i + k, i});
      }
    }
    return Select(seen_error,
                  FullLike(l, std::numeric_limits<float>::quiet_NaN()), l);
  });
}

}  // namespace

bool CholeskyExpander::InstructionMatchesPattern(HloInstruction* instruction) {
  return instruction->opcode() == HloOpcode::kCholesky;
}

StatusOr<HloInstruction*> CholeskyExpander::ExpandInstruction(
    HloInstruction* instruction) {
  const CholeskyOptions& options = instruction->cholesky_options();
  const string name = absl::StrFormat(
      "xla.cholesky_%s_%s", instruction->operand(0)->shape().ToString(),
      options.lower() ? "lower" : "upper");

  HloModule* module = instruction->parent()->parent();

  HloComputation*& computation =
      computation_cache_.emplace(name, nullptr).first->second;
  if (!computation) {
    // Builds a new expansion.
    //
    // TODO(b/62327888): We do something unusual here: we build the computation
    // using the XlaBuilder API, which is nominally an XLA client API. We do
    // this because the external APIs for building complicated computations
    // (XlaBuilder) are much more ergonomic than the internal ones. As it turns
    // out, XlaBuilder isn't really a client API—what it does is build a
    // HloModuleProto protocol buffer, that we can then deserialize and clone
    // into our HloModule. Ideally we would avoid the protocol buffer step;
    // that is left as an exercise for future work.
    XlaBuilder builder(name);
    XlaOp a = Parameter(&builder, 0, instruction->operand(0)->shape(), "a");
    XlaOp l = BuildCholesky(MaybeTransposeInMinorDims(a, !options.lower()),
                            /*block_size=*/128,
                            /*precision=*/PrecisionConfig::HIGHEST);
    MaybeTransposeInMinorDims(l, !options.lower());

    TF_ASSIGN_OR_RETURN(XlaComputation xla_computation, builder.Build());

    TF_ASSIGN_OR_RETURN(ProgramShape program_shape,
                        xla_computation.GetProgramShape());
    HloModuleConfig config(program_shape);
    TF_ASSIGN_OR_RETURN(auto new_module, HloModule::CreateFromProto(
                                             xla_computation.proto(), config));
    HloCloneContext context(module);
    computation =
        module->DeepCloneComputation(new_module->entry_computation(), &context);
  }

  return instruction->parent()->AddInstruction(HloInstruction::CreateCall(
      instruction->shape(), instruction->operands(), computation));
}

}  // namespace xla
<|endoftext|>