<commit_before>/*
 * Copyright (c) 2015-2016 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "LibDS/DriverStation.h"
#include "LibDS/Core/ProtocolBase.h"

using namespace DS_Core;

//=============================================================================
// NetConsole warnings/information texts
//=============================================================================

const QString CHECK_FIREWALL = "
"
                               "ERROR: "
                               "Cannot connect to robot
"
                               "The robot is slow to respond. "
                               "Check firewall settings."
                               "
";
const QString PARTIAL_COMM   = "
"
                               "WARNING: "
                               "%1 responds to ping requests, "
                               "but does not respond to DS packets."
                               "
";
const QString INFO_NOTE      = "
"
                               "NOTE: "
                               ""
                               "The DS may take up to 20 seconds to detect "
                               "your robot, please be patient."
                               "
";
const QString CODE_CRASH     = "
"
                               "WARNING: "
                               ""
                               "The robot code seems to have crashed."
                               "
";
const QString COMM_ESTABLISH = "
"
                               "INFO: "
                               ""
                               "Robot communications established
";

//=============================================================================
//ProtocolBase:DS_ProtocolBase
//=============================================================================

ProtocolBase::ProtocolBase() {
    m_team                = 0;
    m_radioIterator       = 0;
    m_robotIterator       = 0;
    m_sentFMSPackets      = 0;
    m_sentRobotPackets    = 0;

    m_robotAddress        = "";

    m_alliance            = DS::kAllianceRed1;
    m_controlMode         = DS::kControlInvalid;
    m_communicationStatus = DS::kFailing;

    m_enabled             = false;
    m_robotCode           = false;
    m_emergencyStop       = false;
    m_radioConnected      = false;

    m_radioPing.setObjectName ("Radio Ping");
    m_robotPing.setObjectName ("Robot Ping");

    connect (&m_watchdog,  &Watchdog::timeout,
             this,         &ProtocolBase::reset);
    connect (this,         &ProtocolBase::packetReceived,
             &m_watchdog,  &Watchdog::restart);
    connect (&m_robotPing, &QTcpSocket::stateChanged,
             this,         &ProtocolBase::onPingResponse);
    connect (&m_radioPing, &QTcpSocket::stateChanged,
             this,         &ProtocolBase::onPingResponse);

    reset();
    QTimer::singleShot (500, Qt::CoarseTimer, this, SLOT (showPatienceMsg()));
}

//=============================================================================
//ProtocolBase::team
//=============================================================================

int ProtocolBase::team() const {
    return m_team;
}

//=============================================================================
//ProtocolBase::hasCode
//=============================================================================

bool ProtocolBase::hasCode() const {
    return m_robotCode;
}

//=============================================================================
//ProtocolBase::sentFMSPackets
//=============================================================================

int ProtocolBase::sentFmsPackets() const {
    return m_sentFMSPackets;
}

//=============================================================================
//ProtocolBase::sentRobotPackets
//=============================================================================

int ProtocolBase::sentRobotPackets() const {
    return m_sentRobotPackets;
}

//=============================================================================
//ProtocolBase::isEnabled
//=============================================================================

bool ProtocolBase::isEnabled() const {
    return m_enabled;
}

//=============================================================================
//ProtocolBase::isConnectedToRobot
//=============================================================================

bool ProtocolBase::isConnectedToRobot() const {
    return communicationStatus() == DS::kFull;
}

//=============================================================================
//ProtocolBase::isConnectedToRadio
//=============================================================================

bool ProtocolBase::isConnectedToRadio() const {
    return m_radioConnected;
}

//=============================================================================
//ProtocolBase::sendDateTime
//=============================================================================

bool ProtocolBase::sendDateTime() const {
    return m_sendDateTime;
}

//=============================================================================
//ProtocolBase::hasVoltageBrownout
//=============================================================================

bool ProtocolBase::hasVoltageBrownout() const {
    return m_voltageBrownout;
}

//=============================================================================
//ProtocolBase::isEmergencyStopped
//=============================================================================

bool ProtocolBase::isEmergencyStopped() const {
    return m_emergencyStop;
}

//=============================================================================
//ProtocolBase::batteryVoltage
//=============================================================================

float ProtocolBase::batteryVoltage() const {
    return m_voltage;
}

//=============================================================================
//ProtocolBase::alliance
//=============================================================================

DS::Alliance ProtocolBase::alliance() const {
    return m_alliance;
}

//=============================================================================
//ProtocolBase::controlMode
//=============================================================================

DS::ControlMode ProtocolBase::controlMode() const {
    return m_controlMode;
}

//=============================================================================
//ProtocolBase::communicationStatus
//=============================================================================

DS::DS_CommStatus ProtocolBase::communicationStatus() const {
    return m_communicationStatus;
}

//=============================================================================
//ProtocolBase::joysticks
//=============================================================================

QList<DS::Joystick>* ProtocolBase::joysticks() const {
    return DriverStation::getInstance()->joysticks();
}

//=============================================================================
//ProtocolBase::radioAddress
//=============================================================================

QString ProtocolBase::radioAddress() {
    if (m_radioAddress.isEmpty())
        return defaultRadioAddress().at (m_radioIterator);

    return m_radioAddress;
}

//=============================================================================
//ProtocolBase::robotAddress
//=============================================================================

QString ProtocolBase::robotAddress() {
    if (m_robotAddress.isEmpty())
        return defaultRobotAddress().at (m_robotIterator);

    return m_robotAddress;
}

//=============================================================================
//ProtocolBase::createFMSPacket
//=============================================================================

QByteArray ProtocolBase::createFmsPacket() {
    m_sentFMSPackets += 1;
    return _getFmsPacket();
}

//=============================================================================
//ProtocolBase::createPacket
//=============================================================================

QByteArray ProtocolBase::createRobotPacket() {
    m_sentRobotPackets += 1;
    return _getClientPacket();
}

//=============================================================================
//ProtocolBase::reset
//=============================================================================

void ProtocolBase::reset() {
    /* Try another robot address */
    if (m_robotIterator >= defaultRobotAddress().count() - 1)
        m_robotIterator = 0;
    else
        m_robotIterator += 1;

    /* Try another radio address */
    if (m_radioIterator >= defaultRadioAddress().count() - 1)
        m_radioIterator = 0;
    else
        m_radioIterator += 1;

    /* Custom reset procedures for each protocol */
    _resetProtocol();

    /* Emit appropiate signals */
    updateVoltage      (0, 0);
    updateRobotCode    (false);
    updateRadioStatus  (false);
    updateSendDateTime (false);
    updateCommStatus   (DS::kFailing);

    /* Figure out the robot address and ping the robot */
    QHostInfo::lookupHost (robotAddress(),
                           this, SLOT (lookupFinished (QHostInfo)));

    /* Ping robot & radio */
    pingRadio();
    pingRobot();

    /* Lower the watchdog tolerance time to try more robot addresses faster */
    emit robotAddressChanged (robotAddress());
    m_watchdog.setTimeout (125);
}

//=============================================================================
//ProtocolBase::setTeam
//=============================================================================

void ProtocolBase::setTeam (int team) {
    if (team != m_team) {
        m_team = team;
        emit robotAddressChanged (robotAddress());

        DS::log (DS::kLibLevel,
                 "Team number set to: " + QString::number (m_team));
    }
}

//=============================================================================
//ProtocolBase::setEnabled
//=============================================================================

void ProtocolBase::setEnabled (bool enabled) {
    m_enabled = enabled;
    emit enabledChanged (isEnabled());
}

//=============================================================================
//ProtocolBase::setEmergencyStop
//=============================================================================

void ProtocolBase::setEmergencyStop (bool emergency_stop) {
    m_emergencyStop = emergency_stop;
    emit emergencyStoppedChanged (isEmergencyStopped());

    /* Stop sending e-stop packets after 1 second */
    if (m_emergencyStop)
        QTimer::singleShot (1000, this, SLOT (disableEmergencyStop()));

    emit emergencyStopped();
}

//=============================================================================
//ProtocolBase::setRobotAddress
//=============================================================================

void ProtocolBase::setRobotAddress (QString address) {
    m_robotAddress = address;
    emit robotAddressChanged (robotAddress());
}

//=============================================================================
//ProtocolBase::setAlliance
//=============================================================================

void ProtocolBase::setAlliance (DS::Alliance alliance) {
    m_alliance = alliance;
}

//=============================================================================
//ProtocolBase::setControlMode
//=============================================================================

void ProtocolBase::setControlMode (DS::ControlMode mode) {
    if (!isEmergencyStopped()) {
        m_controlMode = mode;
        emit controlModeChanged (controlMode());
    }
}

//=============================================================================
//ProtocolBase::readFMSPacket
//=============================================================================

void ProtocolBase::readFmsPacket (QByteArray data) {
    if (_readFMSPacket (data))
        emit fmsChanged (true);
}

//=============================================================================
//ProtocolBase::readRobotPacket
//=============================================================================

void ProtocolBase::readRobotPacket (QByteArray data) {
    if (!data.isEmpty()) {
        /* We just have connected to the robot, update internal values */
        if (!isConnectedToRobot()) {
            _getRobotInformation();

            setEnabled              (false);
            updateCommStatus        (DS::kFull);
            setControlMode          (DS::kControlTeleoperated);
            DS::sendMessage   (COMM_ESTABLISH);
            DS::log    (DS::kLibLevel,
                        "Robot/DS connection established!");

            /* Make the watchdog tolerance higher to avoid temporary resets */
            m_watchdog.setTimeout (2000);
        }

        /* Let the protocol implementation read the rest of the data */
        if (_readRobotPacket (data))
            emit packetReceived();
    }
}

//=============================================================================
//ProtocolBase::updateRobotCode
//=============================================================================

void ProtocolBase::updateRobotCode (bool available) {
    /* Robot code just crashed/failed */
    if (m_robotCode && !available) {
        setEnabled    (false);
        DS::sendMessage (CODE_CRASH);
        DS::log  (DS::kWarnLevel,
                  "It seems that the robot code crashed");
    }

    /* Update DS information */
    m_robotCode = available;
    emit codeChanged (m_robotCode);
}

//=============================================================================
//ProtocolBase::updateSendDateTime
//=============================================================================

void ProtocolBase::updateSendDateTime (bool sendDT) {
    m_sendDateTime = sendDT;
}

//=============================================================================
//ProtocolBase::updateRadioStatus
//=============================================================================

void ProtocolBase::updateRadioStatus (bool connected) {
    m_radioConnected = connected;
    emit radioCommChanged (m_radioConnected);
}

//=============================================================================
//ProtocolBase::updateCommStatus
//=============================================================================

void ProtocolBase::updateCommStatus (DS::DS_CommStatus status) {
    m_communicationStatus = status;
    emit communicationsChanged (m_communicationStatus);
}

//=============================================================================
//ProtocolBase::updateVoltageBrownout
//=============================================================================

void ProtocolBase::updateVoltageBrownout (bool brownout) {
    m_voltageBrownout = brownout;
    emit voltageBrownoutChanged (m_voltageBrownout);
}

//=============================================================================
//ProtocolBase::updateVoltage
//=============================================================================

void ProtocolBase::updateVoltage (QString digit, QString decimal) {
    /* Voltage is smaller than 10v, add 0 before the digit (e.g. to 09) */
    if (digit.length() < 2)
        digit.prepend ("0");

    /* Decimal voltage is less than 0.1v, add 0 to decimal (e.g 0.01) */
    if (decimal.length() < 2)
        decimal.prepend ("0");

    /* Decimal is too detailed, obtain only first two digits */
    else if (decimal.length() > 2)
        decimal = QString (decimal.at (0)) + QString (decimal.at (1));

    /* Construct voltage string */
    QString voltage = QString ("%1.%2").arg (digit, decimal);

    /* Update values & emit signals */
    m_voltage = voltage.toFloat();
    emit voltageChanged (voltage);
}

//=============================================================================
//ProtocolBase::pingRobot
//=============================================================================

void ProtocolBase::pingRobot() {
    m_robotPing.abort();
    m_robotPing.connectToHost (robotAddress(), tcpProbesPort(),
                               QTcpSocket::ReadOnly);
}

//=============================================================================
//ProtocolBase::pingRadio
//=============================================================================

void ProtocolBase::pingRadio() {
    m_radioPing.abort();
    m_radioPing.connectToHost (radioAddress(), 80, QTcpSocket::ReadOnly);
}

//=============================================================================
//ProtocolBase::showPatienceMsg
//=============================================================================

void ProtocolBase::showPatienceMsg() {
    DS::sendMessage (INFO_NOTE);
}

//=============================================================================
//ProtocolBase::disableEmergencyStop
//=============================================================================

void ProtocolBase::disableEmergencyStop() {
    setEmergencyStop (false);
}

//=============================================================================
//ProtocolBase::updateRobotIP
//=============================================================================

void ProtocolBase::lookupFinished (QHostInfo info) {
    if (!info.addresses().isEmpty())
        emit robotAddressChanged (info.addresses().first().toString());

    pingRobot();
}

//=============================================================================
//ProtocolBase::onPingResponse
//=============================================================================

void ProtocolBase::onPingResponse (QAbstractSocket::SocketState state) {
    bool isAlive = (state == QAbstractSocket::ConnectedState);

    /* Emitter is robot socket */
    if (sender()->objectName() == m_robotPing.objectName()) {
        if (communicationStatus() == DS::kFailing && isAlive)
            updateCommStatus (DS::kPartial);
    }

    /* Emitter is radio socket */
    else if (sender()->objectName() == m_radioPing.objectName())
        updateRadioStatus (isAlive);
}
<commit_msg>Update ProtocolBase.cpp<commit_after>/*
 * Copyright (c) 2015-2016 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "LibDS/DriverStation.h"
#include "LibDS/Core/ProtocolBase.h"

using namespace DS_Core;

//=============================================================================
// NetConsole warnings/information texts
//=============================================================================

const QString CHECK_FIREWALL = "
"
                               "ERROR: "
                               "Cannot connect to robot
"
                               "The robot is slow to respond. "
                               "Check firewall settings."
                               "
";
const QString PARTIAL_COMM   = "
"
                               "WARNING: "
                               "%1 responds to ping requests, "
                               "but does not respond to DS packets."
                               "
";
const QString INFO_NOTE      = "
"
                               "NOTE: "
                               ""
                               "The DS may take up to 20 seconds to detect "
                               "your robot, please be patient."
                               "
";
const QString COMM_ESTABLISH = "
"
                               "INFO: "
                               ""
                               "Robot communications established
";

//=============================================================================
//ProtocolBase:DS_ProtocolBase
//=============================================================================

ProtocolBase::ProtocolBase() {
    m_team                = 0;
    m_radioIterator       = 0;
    m_robotIterator       = 0;
    m_sentFMSPackets      = 0;
    m_sentRobotPackets    = 0;

    m_robotAddress        = "";

    m_alliance            = DS::kAllianceRed1;
    m_controlMode         = DS::kControlInvalid;
    m_communicationStatus = DS::kFailing;

    m_enabled             = false;
    m_robotCode           = false;
    m_emergencyStop       = false;
    m_radioConnected      = false;

    m_radioPing.setObjectName ("Radio Ping");
    m_robotPing.setObjectName ("Robot Ping");

    connect (&m_watchdog,  &Watchdog::timeout,
             this,         &ProtocolBase::reset);
    connect (this,         &ProtocolBase::packetReceived,
             &m_watchdog,  &Watchdog::restart);
    connect (&m_robotPing, &QTcpSocket::stateChanged,
             this,         &ProtocolBase::onPingResponse);
    connect (&m_radioPing, &QTcpSocket::stateChanged,
             this,         &ProtocolBase::onPingResponse);

    reset();
    QTimer::singleShot (500, Qt::CoarseTimer, this, SLOT (showPatienceMsg()));
}

//=============================================================================
//ProtocolBase::team
//=============================================================================

int ProtocolBase::team() const {
    return m_team;
}

//=============================================================================
//ProtocolBase::hasCode
//=============================================================================

bool ProtocolBase::hasCode() const {
    return m_robotCode;
}

//=============================================================================
//ProtocolBase::sentFMSPackets
//=============================================================================

int ProtocolBase::sentFmsPackets() const {
    return m_sentFMSPackets;
}

//=============================================================================
//ProtocolBase::sentRobotPackets
//=============================================================================

int ProtocolBase::sentRobotPackets() const {
    return m_sentRobotPackets;
}

//=============================================================================
//ProtocolBase::isEnabled
//=============================================================================

bool ProtocolBase::isEnabled() const {
    return m_enabled;
}

//=============================================================================
//ProtocolBase::isConnectedToRobot
//=============================================================================

bool ProtocolBase::isConnectedToRobot() const {
    return communicationStatus() == DS::kFull;
}

//=============================================================================
//ProtocolBase::isConnectedToRadio
//=============================================================================

bool ProtocolBase::isConnectedToRadio() const {
    return m_radioConnected;
}

//=============================================================================
//ProtocolBase::sendDateTime
//=============================================================================

bool ProtocolBase::sendDateTime() const {
    return m_sendDateTime;
}

//=============================================================================
//ProtocolBase::hasVoltageBrownout
//=============================================================================

bool ProtocolBase::hasVoltageBrownout() const {
    return m_voltageBrownout;
}

//=============================================================================
//ProtocolBase::isEmergencyStopped
//=============================================================================

bool ProtocolBase::isEmergencyStopped() const {
    return m_emergencyStop;
}

//=============================================================================
//ProtocolBase::batteryVoltage
//=============================================================================

float ProtocolBase::batteryVoltage() const {
    return m_voltage;
}

//=============================================================================
//ProtocolBase::alliance
//=============================================================================

DS::Alliance ProtocolBase::alliance() const {
    return m_alliance;
}

//=============================================================================
//ProtocolBase::controlMode
//=============================================================================

DS::ControlMode ProtocolBase::controlMode() const {
    return m_controlMode;
}

//=============================================================================
//ProtocolBase::communicationStatus
//=============================================================================

DS::DS_CommStatus ProtocolBase::communicationStatus() const {
    return m_communicationStatus;
}

//=============================================================================
//ProtocolBase::joysticks
//=============================================================================

QList<DS::Joystick>* ProtocolBase::joysticks() const {
    return DriverStation::getInstance()->joysticks();
}

//=============================================================================
//ProtocolBase::radioAddress
//=============================================================================

QString ProtocolBase::radioAddress() {
    if (m_radioAddress.isEmpty())
        return defaultRadioAddress().at (m_radioIterator);

    return m_radioAddress;
}

//=============================================================================
//ProtocolBase::robotAddress
//=============================================================================

QString ProtocolBase::robotAddress() {
    if (m_robotAddress.isEmpty())
        return defaultRobotAddress().at (m_robotIterator);

    return m_robotAddress;
}

//=============================================================================
//ProtocolBase::createFMSPacket
//=============================================================================

QByteArray ProtocolBase::createFmsPacket() {
    m_sentFMSPackets += 1;
    return _getFmsPacket();
}

//=============================================================================
//ProtocolBase::createPacket
//=============================================================================

QByteArray ProtocolBase::createRobotPacket() {
    m_sentRobotPackets += 1;
    return _getClientPacket();
}

//=============================================================================
//ProtocolBase::reset
//=============================================================================

void ProtocolBase::reset() {
    /* Try another robot address */
    if (m_robotIterator >= defaultRobotAddress().count() - 1)
        m_robotIterator = 0;
    else
        m_robotIterator += 1;

    /* Try another radio address */
    if (m_radioIterator >= defaultRadioAddress().count() - 1)
        m_radioIterator = 0;
    else
        m_radioIterator += 1;

    /* Custom reset procedures for each protocol */
    _resetProtocol();

    /* Emit appropiate signals */
    updateVoltage      (0, 0);
    updateRobotCode    (false);
    updateRadioStatus  (false);
    updateSendDateTime (false);
    updateCommStatus   (DS::kFailing);

    /* Figure out the robot address and ping the robot */
    QHostInfo::lookupHost (robotAddress(),
                           this, SLOT (lookupFinished (QHostInfo)));

    /* Ping robot & radio */
    pingRadio();
    pingRobot();

    /* Lower the watchdog tolerance time to try more robot addresses faster */
    emit robotAddressChanged (robotAddress());
    m_watchdog.setTimeout (125);
}

//=============================================================================
//ProtocolBase::setTeam
//=============================================================================

void ProtocolBase::setTeam (int team) {
    if (team != m_team) {
        m_team = team;
        emit robotAddressChanged (robotAddress());

        DS::log (DS::kLibLevel,
                 "Team number set to: " + QString::number (m_team));
    }
}

//=============================================================================
//ProtocolBase::setEnabled
//=============================================================================

void ProtocolBase::setEnabled (bool enabled) {
    m_enabled = enabled;
    emit enabledChanged (isEnabled());
}

//=============================================================================
//ProtocolBase::setEmergencyStop
//=============================================================================

void ProtocolBase::setEmergencyStop (bool emergency_stop) {
    m_emergencyStop = emergency_stop;
    emit emergencyStoppedChanged (isEmergencyStopped());

    /* Stop sending e-stop packets after 1 second */
    if (m_emergencyStop)
        QTimer::singleShot (1000, this, SLOT (disableEmergencyStop()));

    emit emergencyStopped();
}

//=============================================================================
//ProtocolBase::setRobotAddress
//=============================================================================

void ProtocolBase::setRobotAddress (QString address) {
    m_robotAddress = address;
    emit robotAddressChanged (robotAddress());
}

//=============================================================================
//ProtocolBase::setAlliance
//=============================================================================

void ProtocolBase::setAlliance (DS::Alliance alliance) {
    m_alliance = alliance;
}

//=============================================================================
//ProtocolBase::setControlMode
//=============================================================================

void ProtocolBase::setControlMode (DS::ControlMode mode) {
    if (!isEmergencyStopped()) {
        m_controlMode = mode;
        emit controlModeChanged (controlMode());
    }
}

//=============================================================================
//ProtocolBase::readFMSPacket
//=============================================================================

void ProtocolBase::readFmsPacket (QByteArray data) {
    if (_readFMSPacket (data))
        emit fmsChanged (true);
}

//=============================================================================
//ProtocolBase::readRobotPacket
//=============================================================================

void ProtocolBase::readRobotPacket (QByteArray data) {
    if (!data.isEmpty()) {
        /* We just have connected to the robot, update internal values */
        if (!isConnectedToRobot()) {
            _getRobotInformation();

            setEnabled              (false);
            updateCommStatus        (DS::kFull);
            setControlMode          (DS::kControlTeleoperated);
            DS::sendMessage   (COMM_ESTABLISH);
            DS::log    (DS::kLibLevel,
                        "Robot/DS connection established!");

            /* Make the watchdog tolerance higher to avoid temporary resets */
            m_watchdog.setTimeout (2000);
        }

        /* Let the protocol implementation read the rest of the data */
        if (_readRobotPacket (data))
            emit packetReceived();
    }
}

//=============================================================================
//ProtocolBase::updateRobotCode
//=============================================================================

void ProtocolBase::updateRobotCode (bool available) {
    /* Robot code just crashed/failed */
    if (m_robotCode && !available)
        setEnabled (false);

    /* Update DS information */
    m_robotCode = available;
    emit codeChanged (m_robotCode);
}

//=============================================================================
//ProtocolBase::updateSendDateTime
//=============================================================================

void ProtocolBase::updateSendDateTime (bool sendDT) {
    m_sendDateTime = sendDT;
}

//=============================================================================
//ProtocolBase::updateRadioStatus
//=============================================================================

void ProtocolBase::updateRadioStatus (bool connected) {
    m_radioConnected = connected;
    emit radioCommChanged (m_radioConnected);
}

//=============================================================================
//ProtocolBase::updateCommStatus
//=============================================================================

void ProtocolBase::updateCommStatus (DS::DS_CommStatus status) {
    m_communicationStatus = status;
    emit communicationsChanged (m_communicationStatus);
}

//=============================================================================
//ProtocolBase::updateVoltageBrownout
//=============================================================================

void ProtocolBase::updateVoltageBrownout (bool brownout) {
    m_voltageBrownout = brownout;
    emit voltageBrownoutChanged (m_voltageBrownout);
}

//=============================================================================
//ProtocolBase::updateVoltage
//=============================================================================

void ProtocolBase::updateVoltage (QString digit, QString decimal) {
    /* Voltage is smaller than 10v, add 0 before the digit (e.g. to 09) */
    if (digit.length() < 2)
        digit.prepend ("0");

    /* Decimal voltage is less than 0.1v, add 0 to decimal (e.g 0.01) */
    if (decimal.length() < 2)
        decimal.prepend ("0");

    /* Decimal is too detailed, obtain only first two digits */
    else if (decimal.length() > 2)
        decimal = QString (decimal.at (0)) + QString (decimal.at (1));

    /* Construct voltage string */
    QString voltage = QString ("%1.%2").arg (digit, decimal);

    /* Update values & emit signals */
    m_voltage = voltage.toFloat();
    emit voltageChanged (voltage);
}

//=============================================================================
//ProtocolBase::pingRobot
//=============================================================================

void ProtocolBase::pingRobot() {
    m_robotPing.abort();
    m_robotPing.connectToHost (robotAddress(), tcpProbesPort(),
                               QTcpSocket::ReadOnly);
}

//=============================================================================
//ProtocolBase::pingRadio
//=============================================================================

void ProtocolBase::pingRadio() {
    m_radioPing.abort();
    m_radioPing.connectToHost (radioAddress(), 80, QTcpSocket::ReadOnly);
}

//=============================================================================
//ProtocolBase::showPatienceMsg
//=============================================================================

void ProtocolBase::showPatienceMsg() {
    DS::sendMessage (INFO_NOTE);
}

//=============================================================================
//ProtocolBase::disableEmergencyStop
//=============================================================================

void ProtocolBase::disableEmergencyStop() {
    setEmergencyStop (false);
}

//=============================================================================
//ProtocolBase::updateRobotIP
//=============================================================================

void ProtocolBase::lookupFinished (QHostInfo info) {
    if (!info.addresses().isEmpty())
        emit robotAddressChanged (info.addresses().first().toString());

    pingRobot();
}

//=============================================================================
//ProtocolBase::onPingResponse
//=============================================================================

void ProtocolBase::onPingResponse (QAbstractSocket::SocketState state) {
    bool isAlive = (state == QAbstractSocket::ConnectedState);

    /* Emitter is robot socket */
    if (sender()->objectName() == m_robotPing.objectName()) {
        if (communicationStatus() == DS::kFailing && isAlive)
            updateCommStatus (DS::kPartial);
    }

    /* Emitter is radio socket */
    else if (sender()->objectName() == m_radioPing.objectName())
        updateRadioStatus (isAlive);
}
<|endoftext|>


<commit_before>/*
	Adam Austin
	4/22/2016
	TA: Quesada
*/

#include "Person.h"
#include "FamilyTree.h"
#include <iostream>
#include <string>

using namespace std;

int main()
{
	FamilyTree *myFamilyTree = new FamilyTree();						// Create an instance of familyTree
	Person *unknownPerson = new Person("Unknown");
	unknownPerson -> setVisited(true);
	myFamilyTree -> setUnknownPerson(unknownPerson);
	bool done = false;
	while (!done)		//write menu
	{
		cout << "======Main Menu======" << endl;
		cout << "1. Add a Person" << endl;
		cout << "2. Print Persons Information" << endl;
		cout << "3. Print Persons Family" << endl;
		cout << "4. Print All Familys" << endl;
		cout << "5. Print all Roots" << endl;
		cout << "6. Quit" << endl;
		string userChoiceString;
		cin >> userChoiceString;

		// Check user input
		if (userChoiceString == "1")
		{
			cout << "What is the persons full name(\"First Last)\"?:" << endl;
			cin.ignore();
			string name;
			getline(cin, name);
			cout << "What is " << name << "'s biological mothers full name, \"First Last\"? If you do not know put \"Unknown\"." << endl;
			string mothersName;
			getline(cin, mothersName);
			cout << "What is " << name << "'s biological fathers full name, \"First Last\"? If you do not know put \"Unknown\"." << endl;
			string fathersName;
			getline(cin, fathersName);
			cout << "Does " << name << " have a spouse? If so, enter their full name, \"First Last\", if not enter \"None\", and if you do not know, enter \"Unknown\"." << endl;
			string spouse;
			getline(cin, spouse);
			cout << "Is " << name << " a male or female? For male enter \"m\" and for female enter \"f\"." << endl;
			string gender = "";
			bool doneWithGender = false;
			while (!doneWithGender)
			{
				getline(cin, gender);
				if (gender == "m" || gender == "f")
				{
					//cout << endl;
					doneWithGender = true;
				}
				else
					cout << "This is not a recognized input, please try again:";
			}
			Person *newPerson = new Person(name, mothersName, fathersName, spouse, gender);
			cout << "Does " << newPerson -> getFullName() << " have any siblings? ";
			bool doneWithSiblings = false;
			while (!doneWithSiblings)
			{
				cout << "If not enter \"No\", otherwise enter their full name, \"First Last\": ";
				//cin.ignore();
				string userInput;
				getline(cin, userInput);
				//cout << "answer was " << userInput << endl;
				if (userInput == "No")
				{
					doneWithSiblings = true;
					//cout << "SAID NO" << endl;
				}
				else
				{
					cout << userInput << " is a sibling? Enter \"Yes \" or \"No\": ";
					string confirm;
					getline(cin, confirm);
					if (confirm == "Yes")
					{
						cout << userInput << " has been added! " << endl;
						Person *newSib = new Person(userInput, myFamilyTree);
						newSib -> addSibling(newPerson);
						newPerson -> addSibling(newSib);
					}
					else
						cout << userInput << " has not been added as a sibling." << endl;
					cout << "Does " << newPerson -> getFullName() << " have any more siblings? ";
				}
			}
			cout << "Does " << newPerson -> getFullName() << " have any children?";
			bool doneWithChildren = false;
			while (!doneWithChildren)
			{
				cout << "If not enter \"No\", otherwise enter their full name, \"First Last\": ";
				//cin.ignore();
				string userInput;
				getline(cin, userInput);
				//cout << "answer was " << userInput << endl;
				if (userInput == "No")
				{
					doneWithChildren = true;
					//cout << "SAID NO" << endl;
				}
				else
				{
					cout << userInput << " is a child? Enter \"Yes \" or \"No\": ";
					string confirm;
					getline(cin, confirm);
					if (confirm == "Yes")
					{
						cout << userInput << " has been added!" << endl;
						Person *newChild = new Person(userInput, myFamilyTree);
						//newChild -> setBi(newPerson);
						newPerson -> addChild(newChild);
					}
					else
						cout << userInput << " has not been added as a child" << endl;
					cout << "Does " << newPerson -> getFullName() << " have any more children?";
				}
			}
			myFamilyTree -> addToTree(newPerson);
		}
		else if (userChoiceString == "2")
		{
			cout << "What is the persons full name(\"First Last)\"?:" << endl;
			cin.ignore();
			string name;
			getline(cin, name);
			//myFamilyTree -> resetVisited();
			Person *person = myFamilyTree -> findPerson(name);
			if (person != NULL)
			{
				person -> printInformation();
			}
		}
		else if (userChoiceString == "3")
		{
			cout << "What is the persons full name(\"First Last)\"?:" << endl;
			cin.ignore();
			string name;
			getline(cin, name);
			//myFamilyTree -> resetVisited();
			Person *person = myFamilyTree -> findPerson(name);
			if (person != NULL)
			{
				myFamilyTree -> printPersonsFamily(person);
			}
		}
		else if (userChoiceString == "5")
		{
			myFamilyTree -> printAllFamilies();
		}
		else if (userChoiceString == "4")
		{
			myFamilyTree -> printAllRoots();
		}
		else if (userChoiceString == "5")
		{
			cout << "Goodbye!" << endl;
			done = true;
		}
	}
	return 0;
}
<commit_msg>added comments to driver<commit_after>/*
	Adam Austin
	4/22/2016
	TA: Quesada
*/

#include "Person.h"
#include "FamilyTree.h"
#include <iostream>
#include <string>

using namespace std;

int main()
{
	FamilyTree *myFamilyTree = new FamilyTree();						// Create an instance of familyTree
	Person *unknownPerson = new Person("Unknown");						// Make an unknown node for the tree whose visited will always be true. This will help with people with unknown relatives
	unknownPerson -> setVisited(true);
	myFamilyTree -> setUnknownPerson(unknownPerson);					// Set the unknown person to myFamilyTree
	bool done = false;
	while (!done)										//write menu
	{
		cout << "======Main Menu======" << endl;
		cout << "1. Add a Person" << endl;
		cout << "2. Print Persons Information" << endl;
		cout << "3. Print Persons Family" << endl;
		cout << "4. Print All Familys" << endl;
		cout << "5. Print all Roots" << endl;
		cout << "6. Quit" << endl;
		string userChoiceString;
		cin >> userChoiceString;

		// Check user input
		if (userChoiceString == "1")	// Add person
		{
			// Get all of the user input to make a new person
			cout << "What is the persons full name(\"First Last)\"?:" << endl;
			cin.ignore();
			string name;
			getline(cin, name);
			cout << "What is " << name << "'s biological mothers full name, \"First Last\"? If you do not know put \"Unknown\"." << endl;
			string mothersName;
			getline(cin, mothersName);
			cout << "What is " << name << "'s biological fathers full name, \"First Last\"? If you do not know put \"Unknown\"." << endl;
			string fathersName;
			getline(cin, fathersName);
			cout << "Does " << name << " have a spouse? If so, enter their full name, \"First Last\", if not enter \"None\", and if you do not know, enter \"Unknown\"." << endl;
			string spouse;
			getline(cin, spouse);
			cout << "Is " << name << " a male or female? For male enter \"m\" and for female enter \"f\"." << endl;
			string gender = "";
			bool doneWithGender = false;
			while (!doneWithGender)
			{
				getline(cin, gender);
				if (gender == "m" || gender == "f")
				{
					//cout << endl;
					doneWithGender = true;
				}
				else
					cout << "This is not a recognized input, please try again:";
			}
			Person *newPerson = new Person(name, mothersName, fathersName, spouse, gender);	// Make a new instance of person with the user input
			cout << "Does " << newPerson -> getFullName() << " have any siblings? ";
			bool doneWithSiblings = false;
			while (!doneWithSiblings)			// Get user input for all siblings
			{
				cout << "If not enter \"No\", otherwise enter their full name, \"First Last\": ";
				string userInput;
				getline(cin, userInput);
				if (userInput == "No" || userInput == "no")				// Check if the person is done with siblings yet
				{
					doneWithSiblings = true;
				}
				else
				{
					cout << userInput << " is a sibling? Enter \"Yes \" or \"No\": ";
					string confirm;
					getline(cin, confirm);
					if (confirm == "Yes" || userInput == "yes")			// If the current input is a sibling
					{
						cout << userInput << " has been added! " << endl;		// Add that sibling to the new persons sibList
						Person *newSib = new Person(userInput, myFamilyTree);
						newSib -> addSibling(newPerson);
						newPerson -> addSibling(newSib);
					}
					else
						cout << userInput << " has not been added as a sibling." << endl;
					cout << "Does " << newPerson -> getFullName() << " have any more siblings? ";
				}
			}
			cout << "Does " << newPerson -> getFullName() << " have any children?";
			bool doneWithChildren = false;
			while (!doneWithChildren)
			{
				cout << "If not enter \"No\", otherwise enter their full name, \"First Last\": ";
				string userInput;
				getline(cin, userInput);
				if (userInput == "No" || userInput == "no")				// Check if the person is done with children yet
				{
					doneWithChildren = true;
				}
				else
				{
					cout << userInput << " is a child? Enter \"Yes \" or \"No\": ";
					string confirm;
					getline(cin, confirm);
					if (confirm == "Yes" || userInput == "yes")				// If the current input is a child
					{
						cout << userInput << " has been added!" << endl;		// Add the child to the new persons childList
						Person *newChild = new Person(userInput, myFamilyTree);
						newPerson -> addChild(newChild);
					}
					else
						cout << userInput << " has not been added as a child" << endl;
					cout << "Does " << newPerson -> getFullName() << " have any more children?";
				}
			}
			myFamilyTree -> addToTree(newPerson);						// Add the new person to the tree
		}
		else if (userChoiceString == "2")	// Print Person information
		{
			cout << "What is the persons full name(\"First Last)\"?:" << endl;
			cin.ignore();
			string name;				// Get user input
			getline(cin, name);
			Person *person = myFamilyTree -> findPerson(name);
			if (person != NULL)
			{
				person -> printInformation();	// Print persons information
			}
		}
		else if (userChoiceString == "3")	// Print persons family
		{
			cout << "What is the persons full name(\"First Last)\"?:" << endl;
			cin.ignore();
			string name;		// Get user input
			getline(cin, name);
			Person *person = myFamilyTree -> findPerson(name);
			if (person != NULL)
			{
				myFamilyTree -> printPersonsFamily(person);		// Print persons family
			}
		}
		else if (userChoiceString == "4")	// Print all families
		{
			myFamilyTree -> printAllFamilies();
		}
		else if (userChoiceString == "5")	// Print all family roots
		{
			myFamilyTree -> printAllRoots();
		}
		else if (userChoiceString == "6")	// Quit
		{
			cout << "Goodbye!" << endl;
			done = true;
		}
	}
	return 0;
}
<|endoftext|>


<commit_before>#pragma once
#include <cmath>

template <typename Type>
class Flock
{
public:
	Flock();
	Type num1;
	Type num2;
	Type num3;

	Flock(Type a, Type b, Type c)
	{
		this->num1 = a;
		this->num2 = b;
		this->num3 = c;
	}

	bool checkFlock()
	{
		// ab + c^a = (a + b - c) + ac^2 * b
		bool condition = this->num1 * this->num2 + std::pow(this->num3, this->num1) == (this->num1 + this->num2 - this->num3) + this->num1 * std::pow(this->num3, 2) * this->num2;
		return condition;
	}

	Type expand()
	{
		Type expandedForm = this->num1 * this->num2 * std::pow(this->num3, 2);
		return expandedForm;
	}

	Type add(Flock a, Flock b)
	{
		Type sum = (a.num1 + b.num1) + (a.num2 + b.num2) + (a.num3 + b.num3);
		return sum;
	}

	Type multiply(Flock a, Flock b)
	{
		Type product = (a.num1 * b.num1) * (a.num2 * b.num2) * (a.num3 * b.num3);
		return product;
	}

	Type subtract(Flock a, Flock b)
	{
		Type diff = (a.num1 - b.num1) - (a.num2 - b.num2) - (a.num3 - b.num3);
		return diff;
	}
};<commit_msg>Clean up some code<commit_after>#pragma once
#include <cmath>

template <typename Type>
class Flock
{
public:
	Flock();
	Type num1;
	Type num2;
	Type num3;

	Flock(Type a, Type b, Type c)
	{
		this->num1 = a;
		this->num2 = b;
		this->num3 = c;
	}

	bool checkFlock()
	{
		// ab + c^a = (a + b - c) + ac^2 * b
		bool condition = num1 * num2 + std::pow(num3, num1) == (num1 + num2 - num3) + num1 * std::pow(num3, 2) * num2;
		return condition;
	}

	Type expand()
	{
		Type expandedForm = num1 * num2 * std::pow(num3, 2);
		return expandedForm;
	}

	Type add(Flock a, Flock b)
	{
		Type sum = (a.num1 + b.num1) + (a.num2 + b.num2) + (a.num3 + b.num3);
		return sum;
	}

	Type multiply(Flock a, Flock b)
	{
		Type product = (a.num1 * b.num1) * (a.num2 * b.num2) * (a.num3 * b.num3);
		return product;
	}

	Type subtract(Flock a, Flock b)
	{
		Type diff = (a.num1 - b.num1) - (a.num2 - b.num2) - (a.num3 - b.num3);
		return diff;
	}
};
<|endoftext|>


<commit_before>//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the "Instituto Nokia de Tecnologia" and
// is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "ARMTargetMachine.h"
#include "ARMTargetAsmInfo.h"
#include "ARMFrameInfo.h"
#include "ARM.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
                              cl::desc("Disable load store optimization pass"));

namespace {
  // Register the target.
  RegisterTarget<ARMTargetMachine> X("arm", "  ARM");
}

/// TargetMachine ctor - Create an ILP32 architecture model
///
ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
  : Subtarget(M, FS),
    DataLayout(Subtarget.isTargetDarwin() ?
               std::string("e-p:32:32-d:32:32-l:32:32") :
               std::string("e-p:32:32-d:32:64-l:32:64")),
    InstrInfo(Subtarget),
    FrameInfo(Subtarget) {}

unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
  std::string TT = M.getTargetTriple();
  if (TT.size() >= 4 && std::string(TT.begin(), TT.begin()+4) == "arm-")
    return 20;

  if (M.getPointerSize() == Module::Pointer32)
    return 1;
  else
    return 0;
}

const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
  return new ARMTargetAsmInfo(*this);
}

// Pass Pipeline Configuration
bool ARMTargetMachine::addInstSelector(FunctionPassManager &PM, bool Fast) {
  PM.add(createARMISelDag(*this));
  return false;
}

bool ARMTargetMachine::addPreEmitPass(FunctionPassManager &PM, bool Fast) {
  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
  if (!Fast && !DisableLdStOpti && !Subtarget.isThumb())
    PM.add(createARMLoadStoreOptimizationPass());

  PM.add(createARMConstantIslandPass());
  return true;
}

bool ARMTargetMachine::addAssemblyEmitter(FunctionPassManager &PM, bool Fast,
                                          std::ostream &Out) {
  // Output assembly language.
  PM.add(createARMCodePrinterPass(Out, *this));
  return false;
}
<commit_msg>Thumb add sp, #imm requires the immediate value be multiple of 4. For now, change preferred alignment of short, byte, bool to 4.<commit_after>//===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the "Instituto Nokia de Tecnologia" and
// is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//

#include "ARMTargetMachine.h"
#include "ARMTargetAsmInfo.h"
#include "ARMFrameInfo.h"
#include "ARM.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
                              cl::desc("Disable load store optimization pass"));

namespace {
  // Register the target.
  RegisterTarget<ARMTargetMachine> X("arm", "  ARM");
}

/// TargetMachine ctor - Create an ILP32 architecture model
///
ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS)
  : Subtarget(M, FS),
    DataLayout(Subtarget.isTargetDarwin() ?
               (Subtarget.isThumb() ?
                std::string("e-p:32:32-d:32:32-l:32:32-s:16:32-b:8:32-B:8:32") :
                std::string("e-p:32:32-d:32:32-l:32:32")) :
               (Subtarget.isThumb() ?
                std::string("e-p:32:32-d:32:64-l:32:64-s:16:32-b:8:32-B:8:32") :
                std::string("e-p:32:32-d:32:64-l:32:64"))),
    InstrInfo(Subtarget),
    FrameInfo(Subtarget) {}

unsigned ARMTargetMachine::getModuleMatchQuality(const Module &M) {
  std::string TT = M.getTargetTriple();
  if (TT.size() >= 4 && std::string(TT.begin(), TT.begin()+4) == "arm-")
    return 20;

  if (M.getPointerSize() == Module::Pointer32)
    return 1;
  else
    return 0;
}

const TargetAsmInfo *ARMTargetMachine::createTargetAsmInfo() const {
  return new ARMTargetAsmInfo(*this);
}

// Pass Pipeline Configuration
bool ARMTargetMachine::addInstSelector(FunctionPassManager &PM, bool Fast) {
  PM.add(createARMISelDag(*this));
  return false;
}

bool ARMTargetMachine::addPreEmitPass(FunctionPassManager &PM, bool Fast) {
  // FIXME: temporarily disabling load / store optimization pass for Thumb mode.
  if (!Fast && !DisableLdStOpti && !Subtarget.isThumb())
    PM.add(createARMLoadStoreOptimizationPass());

  PM.add(createARMConstantIslandPass());
  return true;
}

bool ARMTargetMachine::addAssemblyEmitter(FunctionPassManager &PM, bool Fast,
                                          std::ostream &Out) {
  // Output assembly language.
  PM.add(createARMCodePrinterPass(Out, *this));
  return false;
}
<|endoftext|>


<commit_before>//===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the X86 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//

#include "X86TargetMachine.h"
#include "X86.h"
#include "X86TargetObjectFile.h"
#include "X86TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

static cl::opt<bool> EnableMachineCombinerPass("x86-machine-combiner",
                               cl::desc("Enable the machine combiner pass"),
                               cl::init(true), cl::Hidden);

namespace llvm {
void initializeWinEHStatePassPass(PassRegistry &);
}

extern "C" void LLVMInitializeX86Target() {
  // Register the target.
  RegisterTargetMachine<X86TargetMachine> X(TheX86_32Target);
  RegisterTargetMachine<X86TargetMachine> Y(TheX86_64Target);

  PassRegistry &PR = *PassRegistry::getPassRegistry();
  initializeWinEHStatePassPass(PR);
  initializeFixupBWInstPassPass(PR);
}

static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
  if (TT.isOSBinFormatMachO()) {
    if (TT.getArch() == Triple::x86_64)
      return make_unique<X86_64MachoTargetObjectFile>();
    return make_unique<TargetLoweringObjectFileMachO>();
  }

  if (TT.isOSLinux() || TT.isOSNaCl())
    return make_unique<X86LinuxNaClTargetObjectFile>();
  if (TT.isOSBinFormatELF())
    return make_unique<X86ELFTargetObjectFile>();
  if (TT.isKnownWindowsMSVCEnvironment() || TT.isWindowsCoreCLREnvironment())
    return make_unique<X86WindowsTargetObjectFile>();
  if (TT.isOSBinFormatCOFF())
    return make_unique<TargetLoweringObjectFileCOFF>();
  llvm_unreachable("unknown subtarget type");
}

static std::string computeDataLayout(const Triple &TT) {
  // X86 is little endian
  std::string Ret = "e";

  Ret += DataLayout::getManglingComponent(TT);
  // X86 and x32 have 32 bit pointers.
  if ((TT.isArch64Bit() &&
       (TT.getEnvironment() == Triple::GNUX32 || TT.isOSNaCl())) ||
      !TT.isArch64Bit())
    Ret += "-p:32:32";

  // Some ABIs align 64 bit integers and doubles to 64 bits, others to 32.
  if (TT.isArch64Bit() || TT.isOSWindows() || TT.isOSNaCl())
    Ret += "-i64:64";
  else if (TT.isOSIAMCU())
    Ret += "-i64:32-f64:32";
  else
    Ret += "-f64:32:64";

  // Some ABIs align long double to 128 bits, others to 32.
  if (TT.isOSNaCl() || TT.isOSIAMCU())
    ; // No f80
  else if (TT.isArch64Bit() || TT.isOSDarwin())
    Ret += "-f80:128";
  else
    Ret += "-f80:32";

  if (TT.isOSIAMCU())
    Ret += "-f128:32";

  // The registers can hold 8, 16, 32 or, in x86-64, 64 bits.
  if (TT.isArch64Bit())
    Ret += "-n8:16:32:64";
  else
    Ret += "-n8:16:32";

  // The stack is aligned to 32 bits on some ABIs and 128 bits on others.
  if ((!TT.isArch64Bit() && TT.isOSWindows()) || TT.isOSIAMCU())
    Ret += "-a:0:32-S32";
  else
    Ret += "-S128";

  return Ret;
}

static Reloc::Model getEffectiveRelocModel(const Triple &TT,
                                           Optional<Reloc::Model> RM) {
  bool is64Bit = TT.getArch() == Triple::x86_64;
  if (!RM.hasValue()) {
    // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode.
    // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we
    // use static relocation model by default.
    if (TT.isOSDarwin()) {
      if (is64Bit)
        return Reloc::PIC_;
      return Reloc::DynamicNoPIC;
    }
    if (TT.isOSWindows() && is64Bit)
      return Reloc::PIC_;
    return Reloc::Static;
  }

  // ELF and X86-64 don't have a distinct DynamicNoPIC model.  DynamicNoPIC
  // is defined as a model for code which may be used in static or dynamic
  // executables but not necessarily a shared library. On X86-32 we just
  // compile in -static mode, in x86-64 we use PIC.
  if (*RM == Reloc::DynamicNoPIC) {
    if (is64Bit)
      return Reloc::PIC_;
    if (!TT.isOSDarwin())
      return Reloc::Static;
  }

  // If we are on Darwin, disallow static relocation model in X86-64 mode, since
  // the Mach-O file format doesn't support it.
  if (*RM == Reloc::Static && TT.isOSDarwin() && is64Bit)
    return Reloc::PIC_;

  return *RM;
}

/// Create an X86 target.
///
X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
                                   StringRef CPU, StringRef FS,
                                   const TargetOptions &Options,
                                   Optional<Reloc::Model> RM,
                                   CodeModel::Model CM, CodeGenOpt::Level OL)
    : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
                        getEffectiveRelocModel(TT, RM), CM, OL),
      TLOF(createTLOF(getTargetTriple())),
      Subtarget(TT, CPU, FS, *this, Options.StackAlignmentOverride) {
  // Windows stack unwinder gets confused when execution flow "falls through"
  // after a call to 'noreturn' function.
  // To prevent that, we emit a trap for 'unreachable' IR instructions.
  // (which on X86, happens to be the 'ud2' instruction)
  // On PS4, the "return address" of a 'noreturn' call must still be within
  // the calling function, and TrapUnreachable is an easy way to get that.
  if (Subtarget.isTargetWin64() || Subtarget.isTargetPS4())
    this->Options.TrapUnreachable = true;

  // By default (and when -ffast-math is on), enable estimate codegen for
  // everything except scalar division. By default, use 1 refinement step for
  // all operations. Defaults may be overridden by using command-line options.
  // Scalar division estimates are disabled because they break too much
  // real-world code. These defaults match GCC behavior.
  this->Options.Reciprocals.setDefaults("sqrtf", true, 1);
  this->Options.Reciprocals.setDefaults("divf", false, 1);
  this->Options.Reciprocals.setDefaults("vec-sqrtf", true, 1);
  this->Options.Reciprocals.setDefaults("vec-divf", true, 1);

  initAsmInfo();
}

X86TargetMachine::~X86TargetMachine() {}

const X86Subtarget *
X86TargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  StringRef CPU = !CPUAttr.hasAttribute(Attribute::None)
                      ? CPUAttr.getValueAsString()
                      : (StringRef)TargetCPU;
  StringRef FS = !FSAttr.hasAttribute(Attribute::None)
                     ? FSAttr.getValueAsString()
                     : (StringRef)TargetFS;

  SmallString<512> Key;
  Key.reserve(CPU.size() + FS.size());
  Key += CPU;
  Key += FS;

  // FIXME: This is related to the code below to reset the target options,
  // we need to know whether or not the soft float flag is set on the
  // function before we can generate a subtarget. We also need to use
  // it as a key for the subtarget since that can be the only difference
  // between two functions.
  bool SoftFloat =
      F.getFnAttribute("use-soft-float").getValueAsString() == "true";
  // If the soft float attribute is set on the function turn on the soft float
  // subtarget feature.
  if (SoftFloat)
    Key += FS.empty() ? "+soft-float" : ",+soft-float";

  FS = Key.substr(CPU.size());

  auto &I = SubtargetMap[Key];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
                                        Options.StackAlignmentOverride);
  }
  return I.get();
}

//===----------------------------------------------------------------------===//
// Command line options for x86
//===----------------------------------------------------------------------===//
static cl::opt<bool>
UseVZeroUpper("x86-use-vzeroupper", cl::Hidden,
  cl::desc("Minimize AVX to SSE transition penalty"),
  cl::init(true));

//===----------------------------------------------------------------------===//
// X86 TTI query.
//===----------------------------------------------------------------------===//

TargetIRAnalysis X86TargetMachine::getTargetIRAnalysis() {
  return TargetIRAnalysis([this](const Function &F) {
    return TargetTransformInfo(X86TTIImpl(this, F));
  });
}

//===----------------------------------------------------------------------===//
// Pass Pipeline Configuration
//===----------------------------------------------------------------------===//

namespace {
/// X86 Code Generator Pass Configuration Options.
class X86PassConfig : public TargetPassConfig {
public:
  X86PassConfig(X86TargetMachine *TM, PassManagerBase &PM)
    : TargetPassConfig(TM, PM) {}

  X86TargetMachine &getX86TargetMachine() const {
    return getTM<X86TargetMachine>();
  }

  void addIRPasses() override;
  bool addInstSelector() override;
  bool addILPOpts() override;
  bool addPreISel() override;
  void addPreRegAlloc() override;
  void addPostRegAlloc() override;
  void addPreEmitPass() override;
  void addPreSched2() override;
};
} // namespace

TargetPassConfig *X86TargetMachine::createPassConfig(PassManagerBase &PM) {
  return new X86PassConfig(this, PM);
}

void X86PassConfig::addIRPasses() {
  addPass(createAtomicExpandPass(&getX86TargetMachine()));

  TargetPassConfig::addIRPasses();
}

bool X86PassConfig::addInstSelector() {
  // Install an instruction selector.
  addPass(createX86ISelDag(getX86TargetMachine(), getOptLevel()));

  // For ELF, cleanup any local-dynamic TLS accesses.
  if (TM->getTargetTriple().isOSBinFormatELF() &&
      getOptLevel() != CodeGenOpt::None)
    addPass(createCleanupLocalDynamicTLSPass());

  addPass(createX86GlobalBaseRegPass());
  return false;
}

bool X86PassConfig::addILPOpts() {
  addPass(&EarlyIfConverterID);
  if (EnableMachineCombinerPass)
    addPass(&MachineCombinerID);
  return true;
}

bool X86PassConfig::addPreISel() {
  // Only add this pass for 32-bit x86 Windows.
  const Triple &TT = TM->getTargetTriple();
  if (TT.isOSWindows() && TT.getArch() == Triple::x86)
    addPass(createX86WinEHStatePass());
  return true;
}

void X86PassConfig::addPreRegAlloc() {
  if (getOptLevel() != CodeGenOpt::None) {
    addPass(createX86FixupSetCC());
    addPass(createX86OptimizeLEAs());
    addPass(createX86CallFrameOptimization());
  }

  addPass(createX86WinAllocaExpander());
}

void X86PassConfig::addPostRegAlloc() {
  addPass(createX86FloatingPointStackifierPass());
}

void X86PassConfig::addPreSched2() { addPass(createX86ExpandPseudoPass()); }

void X86PassConfig::addPreEmitPass() {
  if (getOptLevel() != CodeGenOpt::None)
    addPass(createExecutionDependencyFixPass(&X86::VR128XRegClass));

  if (UseVZeroUpper)
    addPass(createX86IssueVZeroUpperPass());

  if (getOptLevel() != CodeGenOpt::None) {
    addPass(createX86FixupBWInsts());
    addPass(createX86PadShortFunctions());
    addPass(createX86FixupLEAs());
  }
}
<commit_msg>Remove a use of subtarget initialization in the X86 backend so we can get rid of the default subtarget.<commit_after>//===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the X86 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//

#include "X86TargetMachine.h"
#include "X86.h"
#include "X86TargetObjectFile.h"
#include "X86TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

static cl::opt<bool> EnableMachineCombinerPass("x86-machine-combiner",
                               cl::desc("Enable the machine combiner pass"),
                               cl::init(true), cl::Hidden);

namespace llvm {
void initializeWinEHStatePassPass(PassRegistry &);
}

extern "C" void LLVMInitializeX86Target() {
  // Register the target.
  RegisterTargetMachine<X86TargetMachine> X(TheX86_32Target);
  RegisterTargetMachine<X86TargetMachine> Y(TheX86_64Target);

  PassRegistry &PR = *PassRegistry::getPassRegistry();
  initializeWinEHStatePassPass(PR);
  initializeFixupBWInstPassPass(PR);
}

static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
  if (TT.isOSBinFormatMachO()) {
    if (TT.getArch() == Triple::x86_64)
      return make_unique<X86_64MachoTargetObjectFile>();
    return make_unique<TargetLoweringObjectFileMachO>();
  }

  if (TT.isOSLinux() || TT.isOSNaCl())
    return make_unique<X86LinuxNaClTargetObjectFile>();
  if (TT.isOSBinFormatELF())
    return make_unique<X86ELFTargetObjectFile>();
  if (TT.isKnownWindowsMSVCEnvironment() || TT.isWindowsCoreCLREnvironment())
    return make_unique<X86WindowsTargetObjectFile>();
  if (TT.isOSBinFormatCOFF())
    return make_unique<TargetLoweringObjectFileCOFF>();
  llvm_unreachable("unknown subtarget type");
}

static std::string computeDataLayout(const Triple &TT) {
  // X86 is little endian
  std::string Ret = "e";

  Ret += DataLayout::getManglingComponent(TT);
  // X86 and x32 have 32 bit pointers.
  if ((TT.isArch64Bit() &&
       (TT.getEnvironment() == Triple::GNUX32 || TT.isOSNaCl())) ||
      !TT.isArch64Bit())
    Ret += "-p:32:32";

  // Some ABIs align 64 bit integers and doubles to 64 bits, others to 32.
  if (TT.isArch64Bit() || TT.isOSWindows() || TT.isOSNaCl())
    Ret += "-i64:64";
  else if (TT.isOSIAMCU())
    Ret += "-i64:32-f64:32";
  else
    Ret += "-f64:32:64";

  // Some ABIs align long double to 128 bits, others to 32.
  if (TT.isOSNaCl() || TT.isOSIAMCU())
    ; // No f80
  else if (TT.isArch64Bit() || TT.isOSDarwin())
    Ret += "-f80:128";
  else
    Ret += "-f80:32";

  if (TT.isOSIAMCU())
    Ret += "-f128:32";

  // The registers can hold 8, 16, 32 or, in x86-64, 64 bits.
  if (TT.isArch64Bit())
    Ret += "-n8:16:32:64";
  else
    Ret += "-n8:16:32";

  // The stack is aligned to 32 bits on some ABIs and 128 bits on others.
  if ((!TT.isArch64Bit() && TT.isOSWindows()) || TT.isOSIAMCU())
    Ret += "-a:0:32-S32";
  else
    Ret += "-S128";

  return Ret;
}

static Reloc::Model getEffectiveRelocModel(const Triple &TT,
                                           Optional<Reloc::Model> RM) {
  bool is64Bit = TT.getArch() == Triple::x86_64;
  if (!RM.hasValue()) {
    // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode.
    // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we
    // use static relocation model by default.
    if (TT.isOSDarwin()) {
      if (is64Bit)
        return Reloc::PIC_;
      return Reloc::DynamicNoPIC;
    }
    if (TT.isOSWindows() && is64Bit)
      return Reloc::PIC_;
    return Reloc::Static;
  }

  // ELF and X86-64 don't have a distinct DynamicNoPIC model.  DynamicNoPIC
  // is defined as a model for code which may be used in static or dynamic
  // executables but not necessarily a shared library. On X86-32 we just
  // compile in -static mode, in x86-64 we use PIC.
  if (*RM == Reloc::DynamicNoPIC) {
    if (is64Bit)
      return Reloc::PIC_;
    if (!TT.isOSDarwin())
      return Reloc::Static;
  }

  // If we are on Darwin, disallow static relocation model in X86-64 mode, since
  // the Mach-O file format doesn't support it.
  if (*RM == Reloc::Static && TT.isOSDarwin() && is64Bit)
    return Reloc::PIC_;

  return *RM;
}

/// Create an X86 target.
///
X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
                                   StringRef CPU, StringRef FS,
                                   const TargetOptions &Options,
                                   Optional<Reloc::Model> RM,
                                   CodeModel::Model CM, CodeGenOpt::Level OL)
    : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
                        getEffectiveRelocModel(TT, RM), CM, OL),
      TLOF(createTLOF(getTargetTriple())),
      Subtarget(TT, CPU, FS, *this, Options.StackAlignmentOverride) {
  // Windows stack unwinder gets confused when execution flow "falls through"
  // after a call to 'noreturn' function.
  // To prevent that, we emit a trap for 'unreachable' IR instructions.
  // (which on X86, happens to be the 'ud2' instruction)
  // On PS4, the "return address" of a 'noreturn' call must still be within
  // the calling function, and TrapUnreachable is an easy way to get that.
  // The check here for 64-bit windows is a bit icky, but as we're unlikely
  // to ever want to mix 32 and 64-bit windows code in a single module
  // this should be fine.
  if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4())
    this->Options.TrapUnreachable = true;

  // By default (and when -ffast-math is on), enable estimate codegen for
  // everything except scalar division. By default, use 1 refinement step for
  // all operations. Defaults may be overridden by using command-line options.
  // Scalar division estimates are disabled because they break too much
  // real-world code. These defaults match GCC behavior.
  this->Options.Reciprocals.setDefaults("sqrtf", true, 1);
  this->Options.Reciprocals.setDefaults("divf", false, 1);
  this->Options.Reciprocals.setDefaults("vec-sqrtf", true, 1);
  this->Options.Reciprocals.setDefaults("vec-divf", true, 1);

  initAsmInfo();
}

X86TargetMachine::~X86TargetMachine() {}

const X86Subtarget *
X86TargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  StringRef CPU = !CPUAttr.hasAttribute(Attribute::None)
                      ? CPUAttr.getValueAsString()
                      : (StringRef)TargetCPU;
  StringRef FS = !FSAttr.hasAttribute(Attribute::None)
                     ? FSAttr.getValueAsString()
                     : (StringRef)TargetFS;

  SmallString<512> Key;
  Key.reserve(CPU.size() + FS.size());
  Key += CPU;
  Key += FS;

  // FIXME: This is related to the code below to reset the target options,
  // we need to know whether or not the soft float flag is set on the
  // function before we can generate a subtarget. We also need to use
  // it as a key for the subtarget since that can be the only difference
  // between two functions.
  bool SoftFloat =
      F.getFnAttribute("use-soft-float").getValueAsString() == "true";
  // If the soft float attribute is set on the function turn on the soft float
  // subtarget feature.
  if (SoftFloat)
    Key += FS.empty() ? "+soft-float" : ",+soft-float";

  FS = Key.substr(CPU.size());

  auto &I = SubtargetMap[Key];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
                                        Options.StackAlignmentOverride);
  }
  return I.get();
}

//===----------------------------------------------------------------------===//
// Command line options for x86
//===----------------------------------------------------------------------===//
static cl::opt<bool>
UseVZeroUpper("x86-use-vzeroupper", cl::Hidden,
  cl::desc("Minimize AVX to SSE transition penalty"),
  cl::init(true));

//===----------------------------------------------------------------------===//
// X86 TTI query.
//===----------------------------------------------------------------------===//

TargetIRAnalysis X86TargetMachine::getTargetIRAnalysis() {
  return TargetIRAnalysis([this](const Function &F) {
    return TargetTransformInfo(X86TTIImpl(this, F));
  });
}

//===----------------------------------------------------------------------===//
// Pass Pipeline Configuration
//===----------------------------------------------------------------------===//

namespace {
/// X86 Code Generator Pass Configuration Options.
class X86PassConfig : public TargetPassConfig {
public:
  X86PassConfig(X86TargetMachine *TM, PassManagerBase &PM)
    : TargetPassConfig(TM, PM) {}

  X86TargetMachine &getX86TargetMachine() const {
    return getTM<X86TargetMachine>();
  }

  void addIRPasses() override;
  bool addInstSelector() override;
  bool addILPOpts() override;
  bool addPreISel() override;
  void addPreRegAlloc() override;
  void addPostRegAlloc() override;
  void addPreEmitPass() override;
  void addPreSched2() override;
};
} // namespace

TargetPassConfig *X86TargetMachine::createPassConfig(PassManagerBase &PM) {
  return new X86PassConfig(this, PM);
}

void X86PassConfig::addIRPasses() {
  addPass(createAtomicExpandPass(&getX86TargetMachine()));

  TargetPassConfig::addIRPasses();
}

bool X86PassConfig::addInstSelector() {
  // Install an instruction selector.
  addPass(createX86ISelDag(getX86TargetMachine(), getOptLevel()));

  // For ELF, cleanup any local-dynamic TLS accesses.
  if (TM->getTargetTriple().isOSBinFormatELF() &&
      getOptLevel() != CodeGenOpt::None)
    addPass(createCleanupLocalDynamicTLSPass());

  addPass(createX86GlobalBaseRegPass());
  return false;
}

bool X86PassConfig::addILPOpts() {
  addPass(&EarlyIfConverterID);
  if (EnableMachineCombinerPass)
    addPass(&MachineCombinerID);
  return true;
}

bool X86PassConfig::addPreISel() {
  // Only add this pass for 32-bit x86 Windows.
  const Triple &TT = TM->getTargetTriple();
  if (TT.isOSWindows() && TT.getArch() == Triple::x86)
    addPass(createX86WinEHStatePass());
  return true;
}

void X86PassConfig::addPreRegAlloc() {
  if (getOptLevel() != CodeGenOpt::None) {
    addPass(createX86FixupSetCC());
    addPass(createX86OptimizeLEAs());
    addPass(createX86CallFrameOptimization());
  }

  addPass(createX86WinAllocaExpander());
}

void X86PassConfig::addPostRegAlloc() {
  addPass(createX86FloatingPointStackifierPass());
}

void X86PassConfig::addPreSched2() { addPass(createX86ExpandPseudoPass()); }

void X86PassConfig::addPreEmitPass() {
  if (getOptLevel() != CodeGenOpt::None)
    addPass(createExecutionDependencyFixPass(&X86::VR128XRegClass));

  if (UseVZeroUpper)
    addPass(createX86IssueVZeroUpperPass());

  if (getOptLevel() != CodeGenOpt::None) {
    addPass(createX86FixupBWInsts());
    addPass(createX86PadShortFunctions());
    addPass(createX86FixupLEAs());
  }
}
<|endoftext|>


<commit_before>//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The StripSymbols transformation implements code stripping. Specifically, it
// can delete:
//
//   * names for virtual registers
//   * symbols for internal globals and functions
//   * debug information
//
// Note that this transformation makes code much less readable, so it should
// only be used in situations where the 'strip' utility would be used, such as
// reducing code size or making it harder to reverse engineer code.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

namespace {
  class StripSymbols : public ModulePass {
    bool OnlyDebugInfo;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripSymbols(bool ODI = false)
      : ModulePass(&ID), OnlyDebugInfo(ODI) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripNonDebugSymbols : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripNonDebugSymbols()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripDebugDeclare : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripDebugDeclare()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };
}

char StripSymbols::ID = 0;
static RegisterPass<StripSymbols>
X("strip", "Strip all symbols from a module");

ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) {
  return new StripSymbols(OnlyDebugInfo);
}

char StripNonDebugSymbols::ID = 0;
static RegisterPass<StripNonDebugSymbols>
Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module");

ModulePass *llvm::createStripNonDebugSymbolsPass() {
  return new StripNonDebugSymbols();
}

char StripDebugDeclare::ID = 0;
static RegisterPass<StripDebugDeclare>
Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics");

ModulePass *llvm::createStripDebugDeclarePass() {
  return new StripDebugDeclare();
}

/// OnlyUsedBy - Return true if V is only used by Usr.
static bool OnlyUsedBy(Value *V, Value *Usr) {
  for(Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
    User *U = *I;
    if (U != Usr)
      return false;
  }
  return true;
}

static void RemoveDeadConstant(Constant *C) {
  assert(C->use_empty() && "Constant is not dead!");
  SmallPtrSet<Constant*, 4> Operands;
  for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
    if (isa<DerivedType>(C->getOperand(i)->getType()) &&
        OnlyUsedBy(C->getOperand(i), C))
      Operands.insert(cast<Constant>(C->getOperand(i)));
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (!GV->hasLocalLinkage()) return;   // Don't delete non static globals.
    GV->eraseFromParent();
  }
  else if (!isa<Function>(C))
    if (isa<CompositeType>(C->getType()))
      C->destroyConstant();

  // If the constant referenced anything, see if we can delete it as well.
  for (SmallPtrSet<Constant*, 4>::iterator OI = Operands.begin(),
         OE = Operands.end(); OI != OE; ++OI)
    RemoveDeadConstant(*OI);
}

// Strip the symbol table of its names.
//
static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
  for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
    Value *V = VI->getValue();
    ++VI;
    if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
      if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg"))
        // Set name to "", removing from symbol table!
        V->setName("");
    }
  }
}

// Strip the symbol table of its names.
static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
  for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
    if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
      ++TI;
    else
      ST.remove(TI++);
  }
}

/// Find values that are marked as llvm.used.
static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;
  UsedValues.insert(LLVMUsed);

  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
  if (Inits == 0) return;

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}

/// StripSymbolNames - Strip symbol names.
static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {

  SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
  }

  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
    StripSymtab(I->getValueSymbolTable(), PreserveDbgInfo);
  }

  // Remove all names from types.
  StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);

  return true;
}

// StripDebugInfo - Strip debug info in the module if it exists.
// To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and
// llvm.dbg.region.end calls, and any globals they point to if now dead.
static bool StripDebugInfo(Module &M) {

  bool Changed = false;

  // Remove all of the calls to the debugger intrinsics, and remove them from
  // the module.
  if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      CI->eraseFromParent();
    }
    Declare->eraseFromParent();
    Changed = true;
  }

  NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv");
  if (NMD) {
    Changed = true;
    NMD->eraseFromParent();
  }

  unsigned MDDbgKind = M.getMDKindID("dbg");
  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE;
         ++FI)
      for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE;
           ++BI)
        BI->setMetadata(MDDbgKind, 0);

  return true;
}

bool StripSymbols::runOnModule(Module &M) {
  bool Changed = false;
  Changed |= StripDebugInfo(M);
  if (!OnlyDebugInfo)
    Changed |= StripSymbolNames(M, false);
  return Changed;
}

bool StripNonDebugSymbols::runOnModule(Module &M) {
  return StripSymbolNames(M, true);
}

bool StripDebugDeclare::runOnModule(Module &M) {

  Function *Declare = M.getFunction("llvm.dbg.declare");
  std::vector<Constant*> DeadConstants;

  if (Declare) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      Value *Arg1 = CI->getOperand(1);
      Value *Arg2 = CI->getOperand(2);
      assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
      CI->eraseFromParent();
      if (Arg1->use_empty()) {
        if (Constant *C = dyn_cast<Constant>(Arg1))
          DeadConstants.push_back(C);
        else
          RecursivelyDeleteTriviallyDeadInstructions(Arg1);
      }
      if (Arg2->use_empty())
        if (Constant *C = dyn_cast<Constant>(Arg2))
          DeadConstants.push_back(C);
    }
    Declare->eraseFromParent();
  }

  while (!DeadConstants.empty()) {
    Constant *C = DeadConstants.back();
    DeadConstants.pop_back();
    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
      if (GV->hasLocalLinkage())
        RemoveDeadConstant(GV);
    } else
      RemoveDeadConstant(C);
  }

  return true;
}
<commit_msg>Strip new llvm.dbg.value intrinsic.<commit_after>//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The StripSymbols transformation implements code stripping. Specifically, it
// can delete:
//
//   * names for virtual registers
//   * symbols for internal globals and functions
//   * debug information
//
// Note that this transformation makes code much less readable, so it should
// only be used in situations where the 'strip' utility would be used, such as
// reducing code size or making it harder to reverse engineer code.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

namespace {
  class StripSymbols : public ModulePass {
    bool OnlyDebugInfo;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripSymbols(bool ODI = false)
      : ModulePass(&ID), OnlyDebugInfo(ODI) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripNonDebugSymbols : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripNonDebugSymbols()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };

  class StripDebugDeclare : public ModulePass {
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit StripDebugDeclare()
      : ModulePass(&ID) {}

    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();
    }
  };
}

char StripSymbols::ID = 0;
static RegisterPass<StripSymbols>
X("strip", "Strip all symbols from a module");

ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) {
  return new StripSymbols(OnlyDebugInfo);
}

char StripNonDebugSymbols::ID = 0;
static RegisterPass<StripNonDebugSymbols>
Y("strip-nondebug", "Strip all symbols, except dbg symbols, from a module");

ModulePass *llvm::createStripNonDebugSymbolsPass() {
  return new StripNonDebugSymbols();
}

char StripDebugDeclare::ID = 0;
static RegisterPass<StripDebugDeclare>
Z("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics");

ModulePass *llvm::createStripDebugDeclarePass() {
  return new StripDebugDeclare();
}

/// OnlyUsedBy - Return true if V is only used by Usr.
static bool OnlyUsedBy(Value *V, Value *Usr) {
  for(Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
    User *U = *I;
    if (U != Usr)
      return false;
  }
  return true;
}

static void RemoveDeadConstant(Constant *C) {
  assert(C->use_empty() && "Constant is not dead!");
  SmallPtrSet<Constant*, 4> Operands;
  for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
    if (isa<DerivedType>(C->getOperand(i)->getType()) &&
        OnlyUsedBy(C->getOperand(i), C))
      Operands.insert(cast<Constant>(C->getOperand(i)));
  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
    if (!GV->hasLocalLinkage()) return;   // Don't delete non static globals.
    GV->eraseFromParent();
  }
  else if (!isa<Function>(C))
    if (isa<CompositeType>(C->getType()))
      C->destroyConstant();

  // If the constant referenced anything, see if we can delete it as well.
  for (SmallPtrSet<Constant*, 4>::iterator OI = Operands.begin(),
         OE = Operands.end(); OI != OE; ++OI)
    RemoveDeadConstant(*OI);
}

// Strip the symbol table of its names.
//
static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
  for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
    Value *V = VI->getValue();
    ++VI;
    if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
      if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg"))
        // Set name to "", removing from symbol table!
        V->setName("");
    }
  }
}

// Strip the symbol table of its names.
static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
  for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) {
    if (PreserveDbgInfo && StringRef(TI->first).startswith("llvm.dbg"))
      ++TI;
    else
      ST.remove(TI++);
  }
}

/// Find values that are marked as llvm.used.
static void findUsedValues(GlobalVariable *LLVMUsed,
                           SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
  if (LLVMUsed == 0) return;
  UsedValues.insert(LLVMUsed);

  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
  if (Inits == 0) return;

  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
    if (GlobalValue *GV =
          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
      UsedValues.insert(GV);
}

/// StripSymbolNames - Strip symbol names.
static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {

  SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);

  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
  }

  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (I->hasLocalLinkage() && llvmUsedValues.count(I) == 0)
      if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg"))
        I->setName("");     // Internal symbols can't participate in linkage
    StripSymtab(I->getValueSymbolTable(), PreserveDbgInfo);
  }

  // Remove all names from types.
  StripTypeSymtab(M.getTypeSymbolTable(), PreserveDbgInfo);

  return true;
}

// StripDebugInfo - Strip debug info in the module if it exists.
// To do this, we remove llvm.dbg.func.start, llvm.dbg.stoppoint, and
// llvm.dbg.region.end calls, and any globals they point to if now dead.
static bool StripDebugInfo(Module &M) {

  bool Changed = false;

  // Remove all of the calls to the debugger intrinsics, and remove them from
  // the module.
  if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      CI->eraseFromParent();
    }
    Declare->eraseFromParent();
    Changed = true;
  }

  if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
    while (!DbgVal->use_empty()) {
      CallInst *CI = cast<CallInst>(DbgVal->use_back());
      CI->eraseFromParent();
    }
    DbgVal->eraseFromParent();
    Changed = true;
  }

  NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv");
  if (NMD) {
    Changed = true;
    NMD->eraseFromParent();
  }

  unsigned MDDbgKind = M.getMDKindID("dbg");
  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
    for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE;
         ++FI)
      for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE;
           ++BI)
        BI->setMetadata(MDDbgKind, 0);

  return true;
}

bool StripSymbols::runOnModule(Module &M) {
  bool Changed = false;
  Changed |= StripDebugInfo(M);
  if (!OnlyDebugInfo)
    Changed |= StripSymbolNames(M, false);
  return Changed;
}

bool StripNonDebugSymbols::runOnModule(Module &M) {
  return StripSymbolNames(M, true);
}

bool StripDebugDeclare::runOnModule(Module &M) {

  Function *Declare = M.getFunction("llvm.dbg.declare");
  std::vector<Constant*> DeadConstants;

  if (Declare) {
    while (!Declare->use_empty()) {
      CallInst *CI = cast<CallInst>(Declare->use_back());
      Value *Arg1 = CI->getOperand(1);
      Value *Arg2 = CI->getOperand(2);
      assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
      CI->eraseFromParent();
      if (Arg1->use_empty()) {
        if (Constant *C = dyn_cast<Constant>(Arg1))
          DeadConstants.push_back(C);
        else
          RecursivelyDeleteTriviallyDeadInstructions(Arg1);
      }
      if (Arg2->use_empty())
        if (Constant *C = dyn_cast<Constant>(Arg2))
          DeadConstants.push_back(C);
    }
    Declare->eraseFromParent();
  }

  while (!DeadConstants.empty()) {
    Constant *C = DeadConstants.back();
    DeadConstants.pop_back();
    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
      if (GV->hasLocalLinkage())
        RemoveDeadConstant(GV);
    } else
      RemoveDeadConstant(C);
  }

  return true;
}
<|endoftext|>