<commit_before>/*******************************************************************************
* Copyright 2016 ROBOTIS CO., LTD.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

/* Authors: Taehoon Lim (Darby) */

#include "dynamixel_workbench_controllers/multi_port.h"

MultiPort::MultiPort()
    :node_handle_("")
{
  std::string device_name[2];
  uint32_t dxl_baud_rate[2];

  device_name[FIRST]    = node_handle_.param<std::string>("pan/device_name", "/dev/ttyUSB0");
  dxl_baud_rate[FIRST]  = node_handle_.param<int>("pan/baud_rate", 57600);

  device_name[SECOND]   = node_handle_.param<std::string>("tilt/device_name", "/dev/ttyUSB1");
  dxl_baud_rate[SECOND] = node_handle_.param<int>("tilt/baud_rate", 57600);

  uint8_t scan_range            = node_handle_.param<int>("scan_range", 200);

  uint32_t profile_velocity     = node_handle_.param<int>("profile_velocity", 200);
  uint32_t profile_acceleration = node_handle_.param<int>("profile_acceleration", 50);

  dxl_wb_[FIRST]  = new DynamixelWorkbench;
  dxl_wb_[SECOND] = new DynamixelWorkbench;

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    dxl_wb_[port_cnt]->begin(device_name[port_cnt].c_str(), dxl_baud_rate[port_cnt]);
    if (dxl_wb_[port_cnt]->scan(dxl_id_[port_cnt], &dxl_cnt_[port_cnt], scan_range) != true)
    {
      ROS_ERROR("Not found Motors, Please check scan range and baud rate");
      ros::shutdown();
      return;
    }
  }
  initMsg();

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
      dxl_wb_[port_cnt]->jointMode(dxl_id_[port_cnt][index], profile_velocity, profile_acceleration);
  }

  initPublisher();
  initServer();
}

MultiPort::~MultiPort()
{
  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
      dxl_wb_[port_cnt]->itemWrite(dxl_id_[port_cnt][index], "Torque_Enable", 0);
  }

  ros::shutdown();
}

void MultiPort::initMsg()
{
  printf("-----------------------------------------------------------------------\n");
  printf("  dynamixel_workbench controller; multi port example                    \n");
  printf("-----------------------------------------------------------------------\n");
  printf("\n");

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
    {
      printf("MODEL   : %s\n", dxl_wb_[port_cnt]->getModelName(dxl_id_[port_cnt][index]));
      printf("ID      : %d\n", dxl_id_[port_cnt][index]);
      printf("\n");
    }
    printf("-----------------------------------------------------------------------\n\n");
  }
}

void MultiPort::initPublisher()
{
  dynamixel_state_list_pub_ = node_handle_.advertise<dynamixel_workbench_msgs::DynamixelStateList>("dynamixel_state", 10);
}

void MultiPort::initServer()
{
  joint_command_server_ = node_handle_.advertiseService("joint_command", &MultiPort::jointCommandMsgCallback, this);
}

void MultiPort::dynamixelStatePublish()
{
  uint8_t dxl_num = dxl_cnt_[FIRST] + dxl_cnt_[SECOND];
  uint8_t cnt = 0;

  dynamixel_workbench_msgs::DynamixelState     dynamixel_state[dxl_num];
  dynamixel_workbench_msgs::DynamixelStateList dynamixel_state_list;

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
    {
      dynamixel_state[cnt].model_name          = std::string(dxl_wb_[port_cnt]->getModelName(dxl_id_[port_cnt][index]));
      dynamixel_state[cnt].id                  = dxl_id_[port_cnt][index];
      dynamixel_state[cnt].torque_enable       = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Torque_Enable");
      dynamixel_state[cnt].present_position    = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Present_Position");
//      dynamixel_state[cnt].present_velocity    = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Present_Velocity"); // "Present_Velocity" or "Present_Speed"
      dynamixel_state[cnt].goal_position       = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Goal_Position");
//      dynamixel_state[cnt].goal_velocity       = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Goal_Velocity");    // "Goal_Velocity" or "Moving_Speed"
      dynamixel_state[cnt].moving              = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Moving");

      dynamixel_state_list.dynamixel_state.push_back(dynamixel_state[cnt]);
      cnt++;
    }
  }
  dynamixel_state_list_pub_.publish(dynamixel_state_list);
}

void MultiPort::controlLoop()
{
  dynamixelStatePublish();
}

bool MultiPort::jointCommandMsgCallback(dynamixel_workbench_msgs::JointCommand::Request &req,
                                              dynamixel_workbench_msgs::JointCommand::Response &res)
{
  int32_t goal_position = 0;
  int32_t present_position = 0;

  uint8_t port = 0;

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
    {
      if (dxl_id_[port_cnt][index] == req.id)
        port = port_cnt;
    }
  }

  if (req.unit == "rad")
  {
    goal_position = dxl_wb_[port]->convertRadian2Value(req.id, req.goal_position);
  }
  else if (req.unit == "raw")
  {
    goal_position = req.goal_position;
  }
  else
  {
    goal_position = req.goal_position;
  }

  bool ret = dxl_wb_[port]->goalPosition(req.id, goal_position);

  res.result = ret;
}

int main(int argc, char **argv)
{
  // Init ROS node
  ros::init(argc, argv, "multi_port");
  MultiPort multi;

  ros::Rate loop_rate(250);

  while (ros::ok())
  {
    multi.controlLoop();
    ros::spinOnce();
    loop_rate.sleep();
  }

  return 0;
}
<commit_msg>delete anotation<commit_after>/*******************************************************************************
* Copyright 2016 ROBOTIS CO., LTD.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/

/* Authors: Taehoon Lim (Darby) */

#include "dynamixel_workbench_controllers/multi_port.h"

MultiPort::MultiPort()
    :node_handle_("")
{
  std::string device_name[2];
  uint32_t dxl_baud_rate[2];

  device_name[FIRST]    = node_handle_.param<std::string>("pan/device_name", "/dev/ttyUSB0");
  dxl_baud_rate[FIRST]  = node_handle_.param<int>("pan/baud_rate", 57600);

  device_name[SECOND]   = node_handle_.param<std::string>("tilt/device_name", "/dev/ttyUSB1");
  dxl_baud_rate[SECOND] = node_handle_.param<int>("tilt/baud_rate", 57600);

  uint8_t scan_range            = node_handle_.param<int>("scan_range", 200);

  uint32_t profile_velocity     = node_handle_.param<int>("profile_velocity", 200);
  uint32_t profile_acceleration = node_handle_.param<int>("profile_acceleration", 50);

  dxl_wb_[FIRST]  = new DynamixelWorkbench;
  dxl_wb_[SECOND] = new DynamixelWorkbench;

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    dxl_wb_[port_cnt]->begin(device_name[port_cnt].c_str(), dxl_baud_rate[port_cnt]);
    if (dxl_wb_[port_cnt]->scan(dxl_id_[port_cnt], &dxl_cnt_[port_cnt], scan_range) != true)
    {
      ROS_ERROR("Not found Motors, Please check scan range and baud rate");
      ros::shutdown();
      return;
    }
  }
  initMsg();

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
      dxl_wb_[port_cnt]->jointMode(dxl_id_[port_cnt][index], profile_velocity, profile_acceleration);
  }

  initPublisher();
  initServer();
}

MultiPort::~MultiPort()
{
  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
      dxl_wb_[port_cnt]->itemWrite(dxl_id_[port_cnt][index], "Torque_Enable", 0);
  }

  ros::shutdown();
}

void MultiPort::initMsg()
{
  printf("-----------------------------------------------------------------------\n");
  printf("  dynamixel_workbench controller; multi port example                    \n");
  printf("-----------------------------------------------------------------------\n");
  printf("\n");

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
    {
      printf("MODEL   : %s\n", dxl_wb_[port_cnt]->getModelName(dxl_id_[port_cnt][index]));
      printf("ID      : %d\n", dxl_id_[port_cnt][index]);
      printf("\n");
    }
    printf("-----------------------------------------------------------------------\n\n");
  }
}

void MultiPort::initPublisher()
{
  dynamixel_state_list_pub_ = node_handle_.advertise<dynamixel_workbench_msgs::DynamixelStateList>("dynamixel_state", 10);
}

void MultiPort::initServer()
{
  joint_command_server_ = node_handle_.advertiseService("joint_command", &MultiPort::jointCommandMsgCallback, this);
}

void MultiPort::dynamixelStatePublish()
{
  uint8_t dxl_num = dxl_cnt_[FIRST] + dxl_cnt_[SECOND];
  uint8_t cnt = 0;

  dynamixel_workbench_msgs::DynamixelState     dynamixel_state[dxl_num];
  dynamixel_workbench_msgs::DynamixelStateList dynamixel_state_list;

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
    {
      dynamixel_state[cnt].model_name          = std::string(dxl_wb_[port_cnt]->getModelName(dxl_id_[port_cnt][index]));
      dynamixel_state[cnt].id                  = dxl_id_[port_cnt][index];
      dynamixel_state[cnt].torque_enable       = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Torque_Enable");
      dynamixel_state[cnt].present_position    = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Present_Position");
      dynamixel_state[cnt].present_velocity    = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Present_Velocity");
      dynamixel_state[cnt].goal_position       = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Goal_Position");
      dynamixel_state[cnt].goal_velocity       = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Goal_Velocity");
      dynamixel_state[cnt].moving              = dxl_wb_[port_cnt]->itemRead(dxl_id_[port_cnt][index], "Moving");

      dynamixel_state_list.dynamixel_state.push_back(dynamixel_state[cnt]);
      cnt++;
    }
  }
  dynamixel_state_list_pub_.publish(dynamixel_state_list);
}

void MultiPort::controlLoop()
{
  dynamixelStatePublish();
}

bool MultiPort::jointCommandMsgCallback(dynamixel_workbench_msgs::JointCommand::Request &req,
                                              dynamixel_workbench_msgs::JointCommand::Response &res)
{
  int32_t goal_position = 0;
  int32_t present_position = 0;

  uint8_t port = 0;

  for (int port_cnt = 0; port_cnt < PORT_NUM; port_cnt++)
  {
    for (int index = 0; index < dxl_cnt_[port_cnt]; index++)
    {
      if (dxl_id_[port_cnt][index] == req.id)
        port = port_cnt;
    }
  }

  if (req.unit == "rad")
  {
    goal_position = dxl_wb_[port]->convertRadian2Value(req.id, req.goal_position);
  }
  else if (req.unit == "raw")
  {
    goal_position = req.goal_position;
  }
  else
  {
    goal_position = req.goal_position;
  }

  bool ret = dxl_wb_[port]->goalPosition(req.id, goal_position);

  res.result = ret;
}

int main(int argc, char **argv)
{
  // Init ROS node
  ros::init(argc, argv, "multi_port");
  MultiPort multi;

  ros::Rate loop_rate(250);

  while (ros::ok())
  {
    multi.controlLoop();
    ros::spinOnce();
    loop_rate.sleep();
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "color.hpp"

#include "ui.hpp"

//#include "ui-buttons.hpp"
//#include "ui-label.hpp"
//#include "ui-textboxes.hpp"
//#include "ui-toggle.hpp"

//#include "glui/GL/glui.h"

using namespace std;

int WIDTH = 1280;  // width of the user window
int HEIGHT = 768;  // height of the user window
char programName[] = "scheduler";

// button info
//vector<Button> buttons;
//vector<Rectangle> boxes;
//vector<TextBox> textboxes;
//vector<Toggle> toggles;
//vector<Label> labels;

const unsigned int MAX_NUM_CHARS_IN_TEXTBOX = 20;

void drawWindow() {
	glClear(GL_COLOR_BUFFER_BIT); // clear the buffer

//	for (vector<Button>::iterator i = buttons.begin(); i != buttons.end(); ++i)      i->draw();
//	for (vector<TextBox>::iterator i = textboxes.begin(); i != textboxes.end(); ++i) i->draw();
//	for (vector<Rectangle>::iterator i = boxes.begin(); i != boxes.end(); ++i)       i->draw();
//	for (vector<Label>::iterator i = labels.begin(); i != labels.end(); ++i)         i->draw();

	glutSwapBuffers(); // tell the graphics card that we're done.
}

// close the window and finish the program
void exitAll() {
	int win = glutGetWindow();
	glutDestroyWindow(win);
	exit(0);
}

// the reshape function handles the case where the user changes the size of the window.  We need to fix the coordinate system, so that the drawing area is still the unit square.
void reshape(int w, int h) {
	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
	WIDTH = w;  HEIGHT = h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0., WIDTH-1, HEIGHT-1, 0., -1.0, 1.0);
}

// initGlWindow is the function that starts the ball rolling, in  terms of getting everything set up and passing control over to the glut library for event handling. It needs to tell the glut library about all the essential functions: what function to call if the window changes shape, what to do to redraw, handle the keyboard, etc.

int main() {
	char *argv[] = { programName };
	int argc = sizeof(argv) / sizeof(argv[0]);
	glutInit(&argc, argv);
	glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
	glutInitWindowSize(WIDTH,HEIGHT);
	glutInitWindowPosition(100,100);
	glutCreateWindow(programName);

	// clear the window to black
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);

	// set up the coordinate system:  number of pixels along x and y
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0., WIDTH-1, HEIGHT-1, 0., -1.0, 1.0);

	// welcome message
	cout << "Welcome to " << programName << endl;

	glutDisplayFunc(drawWindow);
	glutReshapeFunc(reshape);
	glutMainLoop();
}

<commit_msg>Add a tester for the interface<commit_after>#include "color.hpp"

#include "ui.hpp"

//#include "ui-buttons.hpp"
//#include "ui-label.hpp"
//#include "ui-textboxes.hpp"
//#include "ui-toggle.hpp"

//#include "glui/GL/glui.h"

using namespace std;

int WIDTH = 1280;  // width of the user window
int HEIGHT = 768;  // height of the user window
char programName[] = "scheduler";

// button info
//vector<Button> buttons;
//vector<Rectangle> boxes;
//vector<TextBox> textboxes;
//vector<Toggle> toggles;
//vector<Label> labels;

const unsigned int MAX_NUM_CHARS_IN_TEXTBOX = 20;

void drawWindow() {
	glClear(GL_COLOR_BUFFER_BIT); // clear the buffer

//	for (vector<Button>::iterator i = buttons.begin(); i != buttons.end(); ++i)      i->draw();
//	for (vector<TextBox>::iterator i = textboxes.begin(); i != textboxes.end(); ++i) i->draw();
//	for (vector<Rectangle>::iterator i = boxes.begin(); i != boxes.end(); ++i)       i->draw();
//	for (vector<Label>::iterator i = labels.begin(); i != labels.end(); ++i)         i->draw();

	glutSwapBuffers(); // tell the graphics card that we're done.
}

// close the window and finish the program
void exitAll() {
	int win = glutGetWindow();
	glutDestroyWindow(win);
	exit(0);
}

// the reshape function handles the case where the user changes the size of the window.  We need to fix the coordinate system, so that the drawing area is still the unit square.
void reshape(int w, int h) {
	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
	WIDTH = w;  HEIGHT = h;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0., WIDTH-1, HEIGHT-1, 0., -1.0, 1.0);
}

// initGlWindow is the function that starts the ball rolling, in  terms of getting everything set up and passing control over to the glut library for event handling. It needs to tell the glut library about all the essential functions: what function to call if the window changes shape, what to do to redraw, handle the keyboard, etc.

int main() {
	char *argv[] = { programName };
	int argc = sizeof(argv) / sizeof(argv[0]);
	glutInit(&argc, argv);
	glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
	glutInitWindowSize(WIDTH,HEIGHT);
	glutInitWindowPosition(100,100);
	glutCreateWindow(programName);

	// clear the window to black
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);

	// set up the coordinate system:  number of pixels along x and y
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0., WIDTH-1, HEIGHT-1, 0., -1.0, 1.0);

	// welcome message
	cout << "Welcome to " << programName << endl;

	glutDisplayFunc(drawWindow);
	glutReshapeFunc(reshape);
	glutMainLoop();
}

<|endoftext|>


<commit_before>//****************************************************************************
// Copyright © 2015 Jan Erik Breimo. All rights reserved.
// Created by Jan Erik Breimo on 2015-11-22
//
// This file is distributed under the BSD License.
// License text is included with the source distribution.
//****************************************************************************
#include "CodePageEncoder.hpp"
#include "../Unicode/UnicodeChars.hpp"
#include "../YstringException.hpp"

namespace Ystring { namespace Conversion {

    CodePageEncoder::CodePageEncoder(Encoding_t encoding)
        : AbstractEncoder(encoding),
          m_CodePage(Encodings::makeCodePage(encoding))
    {
        // Use ? as replacement character unless the code page supports
        // unicode's designated replacement character.
        setReplacementCharacter('?');
        setReplacementCharacter(Unicode::REPLACEMENT_CHARACTER);
    }

    void CodePageEncoder::setReplacementCharacter(char32_t value)
    {
        if (m_CodePage.fromCodePoint(value) == INVALID_CHAR)
            AbstractEncoder::setReplacementCharacter(value);
    }

    bool CodePageEncoder::doEncode(const char32_t*& srcBeg,
                                   const char32_t* srcEnd,
                                   std::string& dst)
    {
        while (srcBeg != srcEnd)
        {
            auto ch = m_CodePage.fromCodePoint(*srcBeg);
            if (ch != INVALID_CHAR)
            {
                dst.push_back(char(ch));
            }
            else
            {
                switch (errorHandlingPolicy())
                {
                case ErrorHandlingPolicy::REPLACE:
                    dst.push_back(char(replacementCharacter()));
                    break;
                case ErrorHandlingPolicy::STOP:
                    return false;
                case ErrorHandlingPolicy::THROW:
                    YSTRING_THROW("Unsupported code point "
                                  + std::to_string(int64_t(*srcBeg)));
                case ErrorHandlingPolicy::SKIP:
                    break;
                }
            }
            ++srcBeg;
        }
        return true;
    }

}}
<commit_msg>Set the codepage replacement character properly.<commit_after>//****************************************************************************
// Copyright © 2015 Jan Erik Breimo. All rights reserved.
// Created by Jan Erik Breimo on 2015-11-22
//
// This file is distributed under the BSD License.
// License text is included with the source distribution.
//****************************************************************************
#include "CodePageEncoder.hpp"
#include "../Unicode/UnicodeChars.hpp"
#include "../YstringException.hpp"

namespace Ystring { namespace Conversion {

    CodePageEncoder::CodePageEncoder(Encoding_t encoding)
        : AbstractEncoder(encoding),
          m_CodePage(Encodings::makeCodePage(encoding))
    {
        // Use ? as replacement character unless the code page supports
        // unicode's designated replacement character.
        CodePageEncoder::setReplacementCharacter('?');
        CodePageEncoder::setReplacementCharacter(Unicode::REPLACEMENT_CHARACTER);
    }

    void CodePageEncoder::setReplacementCharacter(char32_t value)
    {
        if (m_CodePage.fromCodePoint(value) != INVALID_CHAR)
            AbstractEncoder::setReplacementCharacter(value);
    }

    bool CodePageEncoder::doEncode(const char32_t*& srcBeg,
                                   const char32_t* srcEnd,
                                   std::string& dst)
    {
        while (srcBeg != srcEnd)
        {
            auto ch = m_CodePage.fromCodePoint(*srcBeg);
            if (ch != INVALID_CHAR)
            {
                dst.push_back(char(ch));
            }
            else
            {
                switch (errorHandlingPolicy())
                {
                case ErrorHandlingPolicy::REPLACE:
                    dst.push_back(char(replacementCharacter()));
                    break;
                case ErrorHandlingPolicy::STOP:
                    return false;
                case ErrorHandlingPolicy::THROW:
                    YSTRING_THROW("Unsupported code point "
                                  + std::to_string(int64_t(*srcBeg)));
                case ErrorHandlingPolicy::SKIP:
                    break;
                }
            }
            ++srcBeg;
        }
        return true;
    }

}}
<|endoftext|>


<commit_before><commit_msg>proton-proton-antiproton CF<commit_after><|endoftext|>


<commit_before>//===- Printer.cpp - Code for printing data structure graphs nicely -------===//
//
// This file implements the 'dot' graph printer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/DSGraph.h"
#include "llvm/Analysis/DSGraphTraits.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "Support/CommandLine.h"
#include "Support/GraphWriter.h"
#include <fstream>
#include <sstream>
using std::string;

// OnlyPrintMain - The DataStructure printer exposes this option to allow
// printing of only the graph for "main".
//
static cl::opt<bool> OnlyPrintMain("only-print-main-ds", cl::ReallyHidden);

void DSNode::dump() const { print(std::cerr, 0); }

static string getCaption(const DSNode *N, const DSGraph *G) {
  std::stringstream OS;
  Module *M = G && &G->getFunction() ? G->getFunction().getParent() : 0;

  for (unsigned i = 0, e = N->getTypeEntries().size(); i != e; ++i) {
    WriteTypeSymbolic(OS, N->getTypeEntries()[i].first, M);
    if (N->getTypeEntries()[i].second)
      OS << "@" << N->getTypeEntries()[i].second;
    OS << "\n";
  }

  if (N->NodeType & DSNode::ScalarNode) OS << "S";
  if (N->NodeType & DSNode::AllocaNode) OS << "A";
  if (N->NodeType & DSNode::NewNode   ) OS << "N";
  if (N->NodeType & DSNode::GlobalNode) OS << "G";
  if (N->NodeType & DSNode::Incomplete) OS << "I";

  for (unsigned i = 0, e = N->getGlobals().size(); i != e; ++i) {
    WriteAsOperand(OS, N->getGlobals()[i], false, true, M);
    OS << "\n";
  }

  if ((N->NodeType & DSNode::ScalarNode) && G) {
    const std::map<Value*, DSNodeHandle> &VM = G->getValueMap();
    for (std::map<Value*, DSNodeHandle>::const_iterator I = VM.begin(),
           E = VM.end(); I != E; ++I)
      if (I->second.getNode() == N) {
        WriteAsOperand(OS, I->first, false, true, M);
        OS << "\n";
      }
  }
  return OS.str();
}

static string getValueName(Value *V, Function &F) {
  std::stringstream OS;
  WriteAsOperand(OS, V, true, true, F.getParent());
  return OS.str();
}

static void replaceIn(string &S, char From, const string &To) {
  for (unsigned i = 0; i < S.size(); )
    if (S[i] == From) {
      S.replace(S.begin()+i, S.begin()+i+1,
                To.begin(), To.end());
      i += To.size();
    } else {
      ++i;
    }
}

static std::string escapeLabel(const std::string &In) {
  std::string Label(In);
  replaceIn(Label, '\\', "\\\\");  // Escape caption...
  replaceIn(Label, '\n', "\\n");
  replaceIn(Label, ' ', "\\ ");
  replaceIn(Label, '{', "\\{");
  replaceIn(Label, '}', "\\}");
  return Label;
}

static void writeEdge(std::ostream &O, const void *SrcNode,
                      const char *SrcNodePortName, int SrcNodeIdx,
                      const DSNodeHandle &VS,
                      const std::string &EdgeAttr = "") {
  O << "\tNode" << SrcNode << SrcNodePortName;
  if (SrcNodeIdx != -1) O << SrcNodeIdx;
  O << " -> Node" << (void*)VS.getNode();
  if (VS.getOffset()) O << ":g" << VS.getOffset();

  if (!EdgeAttr.empty())
    O << "[" << EdgeAttr << "]";
  O << ";\n";
}

void DSNode::print(std::ostream &O, const DSGraph *G) const {
  std::string Caption = escapeLabel(getCaption(this, G));

  O << "\tNode" << (void*)this << " [ label =\"{" << Caption;

  unsigned Size = getSize();
  if (Size > 64) Size = 64;   // Don't print out HUGE graph nodes!

  if (getSize() != 0) {
    O << "|{";
    for (unsigned i = 0; i < Size; ++i) {
      if (i) O << "|";
      O << "<g" << i << ">" << (int)MergeMap[i];
    }
    if (Size != getSize())
      O << "|truncated...";
    O << "}";
  }
  O << "}\"];\n";

  for (unsigned i = 0; i != Size; ++i)
    if (const DSNodeHandle *DSN = getLink(i))
      writeEdge(O, this, ":g", i, *DSN);
}

void DSGraph::print(std::ostream &O) const {
  O << "digraph DataStructures {\n"
    << "\tnode [shape=Mrecord];\n"
    << "\tedge [arrowtail=\"dot\"];\n"
    << "\tsize=\"10,7.5\";\n"
    << "\trotate=\"90\";\n";

  if (Func != 0)
    O << "\tlabel=\"Function\\ " << Func->getName() << "\";\n\n";

  // Output all of the nodes...
  for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
    Nodes[i]->print(O, this);

  O << "\n";

  // Output the returned value pointer...
  if (RetNode != 0) {
    O << "\tNode0x1" << "[ plaintext=circle, label =\""
      << escapeLabel("returning") << "\"];\n";
    writeEdge(O, (void*)1, "", -1, RetNode, "arrowtail=tee,color=gray63");
  }

  // Output all of the call nodes...
  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
    const std::vector<DSNodeHandle> &Call = FunctionCalls[i];
    O << "\tNode" << (void*)&Call << " [shape=record,label=\"{call|{";
    for (unsigned j = 0, e = Call.size(); j != e; ++j) {
      if (j) O << "|";
      O << "<g" << j << ">";
    }
    O << "}}\"];\n";

    for (unsigned j = 0, e = Call.size(); j != e; ++j)
      if (Call[j].getNode())
        writeEdge(O, &Call, ":g", j, Call[j], "color=gray63");
  }

  O << "}\n";
}

template<>
struct DOTGraphTraits<DSGraph*> : public DefaultDOTGraphTraits {
  static std::string getGraphName(DSGraph *G) {
    if (G->hasFunction())
      return "Function " + G->getFunction().getName();
    else
      return "Non-function graph";
  }

  static const char *getGraphProperties(DSGraph *G) {
    return "\tnode [shape=Mrecord];\n"
           "\tedge [arrowtail=\"dot\"];\n"
           "\tsize=\"10,7.5\";\n"
           "\trotate=\"90\";\n";
  }

  static std::string getNodeLabel(DSNode *Node, DSGraph *Graph) {
    return getCaption(Node, Graph);
  }

  static std::string getNodeAttributes(DSNode *N) {
    return "";//fontname=Courier";
  }

  //static int getEdgeSourceLabel(DSNode *Node, node_iterator I) {
  //    return MergeMap[i];
  //  }
};

void DSGraph::writeGraphToFile(std::ostream &O, const string &GraphName) {
  string Filename = GraphName + ".dot";
  O << "Writing '" << Filename << "'...";
  std::ofstream F(Filename.c_str());

  if (F.good()) {
    WriteGraph(F, this);
    print(F);
    O << " [" << getGraphSize() << "+" << getFunctionCalls().size() << "]\n";
  } else {
    O << "  error opening file for writing!\n";
  }
}

template <typename Collection>
static void printCollection(const Collection &C, std::ostream &O,
                            const Module *M, const string &Prefix) {
  if (M == 0) {
    O << "Null Module pointer, cannot continue!\n";
    return;
  }

  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal() && (I->getName() == "main" || !OnlyPrintMain))
      C.getDSGraph((Function&)*I).writeGraphToFile(O, Prefix+I->getName());
}

// print - Print out the analysis results...
void LocalDataStructures::print(std::ostream &O, const Module *M) const {
  printCollection(*this, O, M, "ds.");
}

void BUDataStructures::print(std::ostream &O, const Module *M) const {
  printCollection(*this, O, M, "bu.");
#if 0
  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal()) {
      (*getDSGraph(*I).GlobalsGraph)->writeGraphToFile(O, "gg.program");
      break;
    }
#endif
}

#if 0
void TDDataStructures::print(std::ostream &O, const Module *M) const {
  printCollection(*this, O, M, "td.");

  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal()) {
      (*getDSGraph(*I).GlobalsGraph)->writeGraphToFile(O, "gg.program");
      break;
    }
}
#endif
<commit_msg>  - DSGraph Printing Improvements:      * Print edge source labels again      * Override node shape to be Mrecord again, instead of just record.<commit_after>//===- Printer.cpp - Code for printing data structure graphs nicely -------===//
//
// This file implements the 'dot' graph printer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/DSGraph.h"
#include "llvm/Analysis/DSGraphTraits.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "Support/CommandLine.h"
#include "Support/GraphWriter.h"
#include <fstream>
#include <sstream>
using std::string;

// OnlyPrintMain - The DataStructure printer exposes this option to allow
// printing of only the graph for "main".
//
static cl::opt<bool> OnlyPrintMain("only-print-main-ds", cl::ReallyHidden);

void DSNode::dump() const { print(std::cerr, 0); }

static string getCaption(const DSNode *N, const DSGraph *G) {
  std::stringstream OS;
  Module *M = G && &G->getFunction() ? G->getFunction().getParent() : 0;

  for (unsigned i = 0, e = N->getTypeEntries().size(); i != e; ++i) {
    WriteTypeSymbolic(OS, N->getTypeEntries()[i].first, M);
    if (N->getTypeEntries()[i].second)
      OS << "@" << N->getTypeEntries()[i].second;
    OS << "\n";
  }

  if (N->NodeType & DSNode::ScalarNode) OS << "S";
  if (N->NodeType & DSNode::AllocaNode) OS << "A";
  if (N->NodeType & DSNode::NewNode   ) OS << "N";
  if (N->NodeType & DSNode::GlobalNode) OS << "G";
  if (N->NodeType & DSNode::Incomplete) OS << "I";

  for (unsigned i = 0, e = N->getGlobals().size(); i != e; ++i) {
    WriteAsOperand(OS, N->getGlobals()[i], false, true, M);
    OS << "\n";
  }

  if ((N->NodeType & DSNode::ScalarNode) && G) {
    const std::map<Value*, DSNodeHandle> &VM = G->getValueMap();
    for (std::map<Value*, DSNodeHandle>::const_iterator I = VM.begin(),
           E = VM.end(); I != E; ++I)
      if (I->second.getNode() == N) {
        WriteAsOperand(OS, I->first, false, true, M);
        OS << "\n";
      }
  }
  return OS.str();
}

static string getValueName(Value *V, Function &F) {
  std::stringstream OS;
  WriteAsOperand(OS, V, true, true, F.getParent());
  return OS.str();
}

static void replaceIn(string &S, char From, const string &To) {
  for (unsigned i = 0; i < S.size(); )
    if (S[i] == From) {
      S.replace(S.begin()+i, S.begin()+i+1,
                To.begin(), To.end());
      i += To.size();
    } else {
      ++i;
    }
}

static std::string escapeLabel(const std::string &In) {
  std::string Label(In);
  replaceIn(Label, '\\', "\\\\");  // Escape caption...
  replaceIn(Label, '\n', "\\n");
  replaceIn(Label, ' ', "\\ ");
  replaceIn(Label, '{', "\\{");
  replaceIn(Label, '}', "\\}");
  return Label;
}

static void writeEdge(std::ostream &O, const void *SrcNode,
                      const char *SrcNodePortName, int SrcNodeIdx,
                      const DSNodeHandle &VS,
                      const std::string &EdgeAttr = "") {
  O << "\tNode" << SrcNode << SrcNodePortName;
  if (SrcNodeIdx != -1) O << SrcNodeIdx;
  O << " -> Node" << (void*)VS.getNode();
  if (VS.getOffset()) O << ":g" << VS.getOffset();

  if (!EdgeAttr.empty())
    O << "[" << EdgeAttr << "]";
  O << ";\n";
}

void DSNode::print(std::ostream &O, const DSGraph *G) const {
  std::string Caption = escapeLabel(getCaption(this, G));

  O << "\tNode" << (void*)this << " [ label =\"{" << Caption;

  unsigned Size = getSize();
  if (Size > 64) Size = 64;   // Don't print out HUGE graph nodes!

  if (getSize() != 0) {
    O << "|{";
    for (unsigned i = 0; i < Size; ++i) {
      if (i) O << "|";
      O << "<g" << i << ">" << (int)MergeMap[i];
    }
    if (Size != getSize())
      O << "|truncated...";
    O << "}";
  }
  O << "}\"];\n";

  for (unsigned i = 0; i != Size; ++i)
    if (const DSNodeHandle *DSN = getLink(i))
      writeEdge(O, this, ":g", i, *DSN);
}

void DSGraph::print(std::ostream &O) const {
  O << "digraph DataStructures {\n"
    << "\tnode [shape=Mrecord];\n"
    << "\tedge [arrowtail=\"dot\"];\n"
    << "\tsize=\"10,7.5\";\n"
    << "\trotate=\"90\";\n";

  if (Func != 0)
    O << "\tlabel=\"Function\\ " << Func->getName() << "\";\n\n";

  // Output all of the nodes...
  for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
    Nodes[i]->print(O, this);

  O << "\n";

  // Output the returned value pointer...
  if (RetNode != 0) {
    O << "\tNode0x1" << "[ plaintext=circle, label =\""
      << escapeLabel("returning") << "\"];\n";
    writeEdge(O, (void*)1, "", -1, RetNode, "arrowtail=tee,color=gray63");
  }

  // Output all of the call nodes...
  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
    const std::vector<DSNodeHandle> &Call = FunctionCalls[i];
    O << "\tNode" << (void*)&Call << " [shape=record,label=\"{call|{";
    for (unsigned j = 0, e = Call.size(); j != e; ++j) {
      if (j) O << "|";
      O << "<g" << j << ">";
    }
    O << "}}\"];\n";

    for (unsigned j = 0, e = Call.size(); j != e; ++j)
      if (Call[j].getNode())
        writeEdge(O, &Call, ":g", j, Call[j], "color=gray63");
  }

  O << "}\n";
}

template<>
struct DOTGraphTraits<DSGraph*> : public DefaultDOTGraphTraits {
  static std::string getGraphName(DSGraph *G) {
    if (G->hasFunction())
      return "Function " + G->getFunction().getName();
    else
      return "Non-function graph";
  }

  static const char *getGraphProperties(DSGraph *G) {
    return "\tedge [arrowtail=\"dot\"];\n"
           "\tsize=\"10,7.5\";\n"
           "\trotate=\"90\";\n";
  }

  static std::string getNodeLabel(DSNode *Node, DSGraph *Graph) {
    return getCaption(Node, Graph);
  }

  static std::string getNodeAttributes(DSNode *N) {
    return "shape=Mrecord";//fontname=Courier";
  }

  static int getEdgeSourceLabel(DSNode *Node, DSNode::iterator I) {
    assert(Node == I.getNode() && "Iterator not for this node!");
    return Node->getMergeMapLabel(I.getLink());
  }
};

void DSGraph::writeGraphToFile(std::ostream &O, const string &GraphName) {
  string Filename = GraphName + ".dot";
  O << "Writing '" << Filename << "'...";
  std::ofstream F(Filename.c_str());

  if (F.good()) {
    WriteGraph(F, this);
    //print(F);
    O << " [" << getGraphSize() << "+" << getFunctionCalls().size() << "]\n";
  } else {
    O << "  error opening file for writing!\n";
  }
}

template <typename Collection>
static void printCollection(const Collection &C, std::ostream &O,
                            const Module *M, const string &Prefix) {
  if (M == 0) {
    O << "Null Module pointer, cannot continue!\n";
    return;
  }

  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal() && (I->getName() == "main" || !OnlyPrintMain))
      C.getDSGraph((Function&)*I).writeGraphToFile(O, Prefix+I->getName());
}

// print - Print out the analysis results...
void LocalDataStructures::print(std::ostream &O, const Module *M) const {
  printCollection(*this, O, M, "ds.");
}

void BUDataStructures::print(std::ostream &O, const Module *M) const {
  printCollection(*this, O, M, "bu.");
#if 0
  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal()) {
      (*getDSGraph(*I).GlobalsGraph)->writeGraphToFile(O, "gg.program");
      break;
    }
#endif
}

#if 0
void TDDataStructures::print(std::ostream &O, const Module *M) const {
  printCollection(*this, O, M, "td.");

  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal()) {
      (*getDSGraph(*I).GlobalsGraph)->writeGraphToFile(O, "gg.program");
      break;
    }
}
#endif
<|endoftext|>


<commit_before>//===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a concrete implementation of profiling information that
// loads the information from a profile dump file.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "profile-loader"
#include "llvm/BasicBlock.h"
#include "llvm/InstrTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Analysis/ProfileInfoLoader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallSet.h"
#include <set>
using namespace llvm;

STATISTIC(NumEdgesRead, "The # of edges read.");

static cl::opt<std::string>
ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"),
                    cl::value_desc("filename"),
                    cl::desc("Profile file loaded by -profile-loader"));

namespace {
  class LoaderPass : public ModulePass, public ProfileInfo {
    std::string Filename;
    std::set<Edge> SpanningTree;
    std::set<const BasicBlock*> BBisUnvisited;
    unsigned ReadCount;
  public:
    static char ID; // Class identification, replacement for typeinfo
    explicit LoaderPass(const std::string &filename = "")
      : ModulePass(&ID), Filename(filename) {
      if (filename.empty()) Filename = ProfileInfoFilename;
    }

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

    virtual const char *getPassName() const {
      return "Profiling information loader";
    }

    // recurseBasicBlock() - Calculates the edge weights for as much basic
    // blocks as possbile.
    virtual void recurseBasicBlock(const BasicBlock *BB);
    virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &);
    virtual void readEdge(ProfileInfo::Edge, std::vector<unsigned>&);

    /// run - Load the profile information from the specified file.
    virtual bool runOnModule(Module &M);
  };
}  // End of anonymous namespace

char LoaderPass::ID = 0;
static RegisterPass<LoaderPass>
X("profile-loader", "Load profile information from llvmprof.out", false, true);

static RegisterAnalysisGroup<ProfileInfo> Y(X);

const PassInfo *llvm::ProfileLoaderPassID = &X;

ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); }

/// createProfileLoaderPass - This function returns a Pass that loads the
/// profiling information for the module from the specified filename, making it
/// available to the optimizers.
Pass *llvm::createProfileLoaderPass(const std::string &Filename) {
  return new LoaderPass(Filename);
}

void LoaderPass::readEdgeOrRemember(Edge edge, Edge &tocalc,
                                    unsigned &uncalc, double &count) {
  double w;
  if ((w = getEdgeWeight(edge)) == MissingValue) {
    tocalc = edge;
    uncalc++;
  } else {
    count+=w;
  }
}

// recurseBasicBlock - Visits all neighbours of a block and then tries to
// calculate the missing edge values.
void LoaderPass::recurseBasicBlock(const BasicBlock *BB) {

  // break recursion if already visited
  if (BBisUnvisited.find(BB) == BBisUnvisited.end()) return;
  BBisUnvisited.erase(BB);
  if (!BB) return;

  for (succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
       bbi != bbe; ++bbi) {
    recurseBasicBlock(*bbi);
  }
  for (pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
       bbi != bbe; ++bbi) {
    recurseBasicBlock(*bbi);
  }

  Edge tocalc;
  if (CalculateMissingEdge(BB, tocalc)) {
    SpanningTree.erase(tocalc);
  }
}

void LoaderPass::readEdge(ProfileInfo::Edge e,
                          std::vector<unsigned> &ECs) {
  if (ReadCount < ECs.size()) {
    double weight = ECs[ReadCount++];
    if (weight != ProfileInfoLoader::Uncounted) {
      // Here the data realm changes from the unsigned of the file to the
      // double of the ProfileInfo. This conversion is save because we know
      // that everything thats representable in unsinged is also representable
      // in double.
      EdgeInformation[getFunction(e)][e] += (double)weight;

      DEBUG(dbgs() << "--Read Edge Counter for " << e
                   << " (# "<< (ReadCount-1) << "): "
                   << (unsigned)getEdgeWeight(e) << "\n");
    } else {
      // This happens only if reading optimal profiling information, not when
      // reading regular profiling information.
      SpanningTree.insert(e);
    }
  }
}

bool LoaderPass::runOnModule(Module &M) {
  ProfileInfoLoader PIL("profile-loader", Filename, M);

  EdgeInformation.clear();
  std::vector<unsigned> Counters = PIL.getRawEdgeCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
      readEdge(getEdge(0,&F->getEntryBlock()), Counters);
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        TerminatorInst *TI = BB->getTerminator();
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
        }
      }
    }
    if (ReadCount != Counters.size()) {
      dbgs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
    NumEdgesRead = ReadCount;
  }

  Counters = PIL.getRawOptimalEdgeCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
      readEdge(getEdge(0,&F->getEntryBlock()), Counters);
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        TerminatorInst *TI = BB->getTerminator();
        if (TI->getNumSuccessors() == 0) {
          readEdge(getEdge(BB,0), Counters);
        }
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
        }
      }
      while (SpanningTree.size() > 0) {

        unsigned size = SpanningTree.size();

        BBisUnvisited.clear();
        for (std::set<Edge>::iterator ei = SpanningTree.begin(),
             ee = SpanningTree.end(); ei != ee; ++ei) {
          BBisUnvisited.insert(ei->first);
          BBisUnvisited.insert(ei->second);
        }
        while (BBisUnvisited.size() > 0) {
          recurseBasicBlock(*BBisUnvisited.begin());
        }

        if (SpanningTree.size() == size) {
          DEBUG(dbgs()<<"{");
          for (std::set<Edge>::iterator ei = SpanningTree.begin(),
               ee = SpanningTree.end(); ei != ee; ++ei) {
            DEBUG(dbgs()<< *ei <<",");
          }
          assert(0 && "No edge calculated!");
        }

      }
    }
    if (ReadCount != Counters.size()) {
      dbgs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
    NumEdgesRead = ReadCount;
  }

  BlockInformation.clear();
  Counters = PIL.getRawBlockCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
        if (ReadCount < Counters.size())
          // Here the data realm changes from the unsigned of the file to the
          // double of the ProfileInfo. This conversion is save because we know
          // that everything thats representable in unsinged is also
          // representable in double.
          BlockInformation[F][BB] = (double)Counters[ReadCount++];
    }
    if (ReadCount != Counters.size()) {
      dbgs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
  }

  FunctionInformation.clear();
  Counters = PIL.getRawFunctionCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      if (ReadCount < Counters.size())
        // Here the data realm changes from the unsigned of the file to the
        // double of the ProfileInfo. This conversion is save because we know
        // that everything thats representable in unsinged is also
        // representable in double.
        FunctionInformation[F] = (double)Counters[ReadCount++];
    }
    if (ReadCount != Counters.size()) {
      dbgs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
  }

  return false;
}
<commit_msg><commit_after>//===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a concrete implementation of profiling information that
// loads the information from a profile dump file.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "profile-loader"
#include "llvm/BasicBlock.h"
#include "llvm/InstrTypes.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Analysis/ProfileInfoLoader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallSet.h"
#include <set>
using namespace llvm;

STATISTIC(NumEdgesRead, "The # of edges read.");

static cl::opt<std::string>
ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"),
                    cl::value_desc("filename"),
                    cl::desc("Profile file loaded by -profile-loader"));

namespace {
  class LoaderPass : public ModulePass, public ProfileInfo {
    std::string Filename;
    std::set<Edge> SpanningTree;
    std::set<const BasicBlock*> BBisUnvisited;
    unsigned ReadCount;
  public:
    static char ID; // Class identification, replacement for typeinfo
    explicit LoaderPass(const std::string &filename = "")
      : ModulePass(&ID), Filename(filename) {
      if (filename.empty()) Filename = ProfileInfoFilename;
    }

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

    virtual const char *getPassName() const {
      return "Profiling information loader";
    }

    // recurseBasicBlock() - Calculates the edge weights for as much basic
    // blocks as possbile.
    virtual void recurseBasicBlock(const BasicBlock *BB);
    virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &);
    virtual void readEdge(ProfileInfo::Edge, std::vector<unsigned>&);

    /// run - Load the profile information from the specified file.
    virtual bool runOnModule(Module &M);
  };
}  // End of anonymous namespace

char LoaderPass::ID = 0;
static RegisterPass<LoaderPass>
X("profile-loader", "Load profile information from llvmprof.out", false, true);

static RegisterAnalysisGroup<ProfileInfo> Y(X);

const PassInfo *llvm::ProfileLoaderPassID = &X;

ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); }

/// createProfileLoaderPass - This function returns a Pass that loads the
/// profiling information for the module from the specified filename, making it
/// available to the optimizers.
Pass *llvm::createProfileLoaderPass(const std::string &Filename) {
  return new LoaderPass(Filename);
}

void LoaderPass::readEdgeOrRemember(Edge edge, Edge &tocalc,
                                    unsigned &uncalc, double &count) {
  double w;
  if ((w = getEdgeWeight(edge)) == MissingValue) {
    tocalc = edge;
    uncalc++;
  } else {
    count+=w;
  }
}

// recurseBasicBlock - Visits all neighbours of a block and then tries to
// calculate the missing edge values.
void LoaderPass::recurseBasicBlock(const BasicBlock *BB) {

  // break recursion if already visited
  if (BBisUnvisited.find(BB) == BBisUnvisited.end()) return;
  BBisUnvisited.erase(BB);
  if (!BB) return;

  for (succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
       bbi != bbe; ++bbi) {
    recurseBasicBlock(*bbi);
  }
  for (pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
       bbi != bbe; ++bbi) {
    recurseBasicBlock(*bbi);
  }

  Edge tocalc;
  if (CalculateMissingEdge(BB, tocalc)) {
    SpanningTree.erase(tocalc);
  }
}

void LoaderPass::readEdge(ProfileInfo::Edge e,
                          std::vector<unsigned> &ECs) {
  if (ReadCount < ECs.size()) {
    double weight = ECs[ReadCount++];
    if (weight != ProfileInfoLoader::Uncounted) {
      // Here the data realm changes from the unsigned of the file to the
      // double of the ProfileInfo. This conversion is save because we know
      // that everything thats representable in unsinged is also representable
      // in double.
      EdgeInformation[getFunction(e)][e] += (double)weight;

      DEBUG(dbgs() << "--Read Edge Counter for " << e
                   << " (# "<< (ReadCount-1) << "): "
                   << (unsigned)getEdgeWeight(e) << "\n");
    } else {
      // This happens only if reading optimal profiling information, not when
      // reading regular profiling information.
      SpanningTree.insert(e);
    }
  }
}

bool LoaderPass::runOnModule(Module &M) {
  ProfileInfoLoader PIL("profile-loader", Filename, M);

  EdgeInformation.clear();
  std::vector<unsigned> Counters = PIL.getRawEdgeCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
      readEdge(getEdge(0,&F->getEntryBlock()), Counters);
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        TerminatorInst *TI = BB->getTerminator();
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
        }
      }
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
    NumEdgesRead = ReadCount;
  }

  Counters = PIL.getRawOptimalEdgeCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
      readEdge(getEdge(0,&F->getEntryBlock()), Counters);
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
        TerminatorInst *TI = BB->getTerminator();
        if (TI->getNumSuccessors() == 0) {
          readEdge(getEdge(BB,0), Counters);
        }
        for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
          readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
        }
      }
      while (SpanningTree.size() > 0) {

        unsigned size = SpanningTree.size();

        BBisUnvisited.clear();
        for (std::set<Edge>::iterator ei = SpanningTree.begin(),
             ee = SpanningTree.end(); ei != ee; ++ei) {
          BBisUnvisited.insert(ei->first);
          BBisUnvisited.insert(ei->second);
        }
        while (BBisUnvisited.size() > 0) {
          recurseBasicBlock(*BBisUnvisited.begin());
        }

        if (SpanningTree.size() == size) {
          DEBUG(dbgs()<<"{");
          for (std::set<Edge>::iterator ei = SpanningTree.begin(),
               ee = SpanningTree.end(); ei != ee; ++ei) {
            DEBUG(dbgs()<< *ei <<",");
          }
          assert(0 && "No edge calculated!");
        }

      }
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
    NumEdgesRead = ReadCount;
  }

  BlockInformation.clear();
  Counters = PIL.getRawBlockCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
        if (ReadCount < Counters.size())
          // Here the data realm changes from the unsigned of the file to the
          // double of the ProfileInfo. This conversion is save because we know
          // that everything thats representable in unsinged is also
          // representable in double.
          BlockInformation[F][BB] = (double)Counters[ReadCount++];
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
  }

  FunctionInformation.clear();
  Counters = PIL.getRawFunctionCounts();
  if (Counters.size() > 0) {
    ReadCount = 0;
    for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
      if (F->isDeclaration()) continue;
      if (ReadCount < Counters.size())
        // Here the data realm changes from the unsigned of the file to the
        // double of the ProfileInfo. This conversion is save because we know
        // that everything thats representable in unsinged is also
        // representable in double.
        FunctionInformation[F] = (double)Counters[ReadCount++];
    }
    if (ReadCount != Counters.size()) {
      errs() << "WARNING: profile information is inconsistent with "
             << "the current program!\n";
    }
  }

  return false;
}
<|endoftext|>


<commit_before>//===- ReaderWrappers.cpp - Parse bytecode from file or buffer  -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements loading and parsing a bytecode file and parsing a
// bytecode module from a given buffer.
//
//===----------------------------------------------------------------------===//

#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "Support/StringExtras.h"
#include "Config/fcntl.h"
#include <sys/stat.h>
#include "Config/unistd.h"
#include "Config/sys/mman.h"

namespace llvm {

//===----------------------------------------------------------------------===//
// BytecodeFileReader - Read from an mmap'able file descriptor.
//

namespace {
  /// FDHandle - Simple handle class to make sure a file descriptor gets closed
  /// when the object is destroyed.
  ///
  class FDHandle {
    int FD;
  public:
    FDHandle(int fd) : FD(fd) {}
    operator int() const { return FD; }
    ~FDHandle() {
      if (FD != -1) close(FD);
    }
  };

  /// BytecodeFileReader - parses a bytecode file from a file
  ///
  class BytecodeFileReader : public BytecodeParser {
  private:
    unsigned char *Buffer;
    int Length;

    BytecodeFileReader(const BytecodeFileReader&); // Do not implement
    void operator=(const BytecodeFileReader &BFR); // Do not implement

  public:
    BytecodeFileReader(const std::string &Filename);
    ~BytecodeFileReader();
  };
}

BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
  FDHandle FD = open(Filename.c_str(), O_RDONLY);
  if (FD == -1)
    throw std::string("Error opening file!");

  // Stat the file to get its length...
  struct stat StatBuf;
  if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
    throw std::string("Error stat'ing file!");

  // mmap in the file all at once...
  Length = StatBuf.st_size;
  Buffer = (unsigned char*)mmap(0, Length, PROT_READ, MAP_PRIVATE, FD, 0);

  if (Buffer == (unsigned char*)MAP_FAILED)
    throw std::string("Error mmapping file!");

  try {
    // Parse the bytecode we mmapped in
    ParseBytecode(Buffer, Length, Filename);
  } catch (...) {
    munmap((char*)Buffer, Length);
    throw;
  }
}

BytecodeFileReader::~BytecodeFileReader() {
  // Unmmap the bytecode...
  munmap((char*)Buffer, Length);
}

//===----------------------------------------------------------------------===//
// BytecodeBufferReader - Read from a memory buffer
//

namespace {
  /// BytecodeBufferReader - parses a bytecode file from a buffer
  ///
  class BytecodeBufferReader : public BytecodeParser {
  private:
    const unsigned char *Buffer;
    bool MustDelete;

    BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
    void operator=(const BytecodeBufferReader &BFR);   // Do not implement

  public:
    BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
                         const std::string &ModuleID);
    ~BytecodeBufferReader();

  };
}

BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
                                           unsigned Length,
                                           const std::string &ModuleID)
{
  // If not aligned, allocate a new buffer to hold the bytecode...
  const unsigned char *ParseBegin = 0;
  if ((intptr_t)Buf & 3) {
    Buffer = new unsigned char[Length+4];
    unsigned Offset = 4 - ((intptr_t)Buffer & 3);   // Make sure it's aligned
    ParseBegin = Buffer + Offset;
    memcpy((unsigned char*)ParseBegin, Buf, Length);    // Copy it over
    MustDelete = true;
  } else {
    // If we don't need to copy it over, just use the caller's copy
    ParseBegin = Buffer = Buf;
    MustDelete = false;
  }
  try {
    ParseBytecode(ParseBegin, Length, ModuleID);
  } catch (...) {
    if (MustDelete) delete [] Buffer;
    throw;
  }
}

BytecodeBufferReader::~BytecodeBufferReader() {
  if (MustDelete) delete [] Buffer;
}

//===----------------------------------------------------------------------===//
//  BytecodeStdinReader - Read bytecode from Standard Input
//

namespace {
  /// BytecodeStdinReader - parses a bytecode file from stdin
  ///
  class BytecodeStdinReader : public BytecodeParser {
  private:
    std::vector<unsigned char> FileData;
    unsigned char *FileBuf;

    BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
    void operator=(const BytecodeStdinReader &BFR);  // Do not implement

  public:
    BytecodeStdinReader();
  };
}

BytecodeStdinReader::BytecodeStdinReader() {
  int BlockSize;
  unsigned char Buffer[4096*4];

  // Read in all of the data from stdin, we cannot mmap stdin...
  while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) {
    if (BlockSize == -1)
      throw std::string("Error reading from stdin!");

    FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
  }

  if (FileData.empty())
    throw std::string("Standard Input empty!");

  FileBuf = &FileData[0];
  ParseBytecode(FileBuf, FileData.size(), "<stdin>");
}

//===----------------------------------------------------------------------===//
//  Varargs transmogrification code...
//

// CheckVarargs - This is used to automatically translate old-style varargs to
// new style varargs for backwards compatibility.
static ModuleProvider *CheckVarargs(ModuleProvider *MP) {
  Module *M = MP->getModule();

  // Check to see if va_start takes arguments...
  Function *F = M->getNamedFunction("llvm.va_start");
  if (F == 0) return MP;  // No varargs use, just return.

  if (F->getFunctionType()->getNumParams() == 0)
    return MP;  // Modern varargs processing, just return.

  // If we get to this point, we know that we have an old-style module.
  // Materialize the whole thing to perform the rewriting.
  MP->materializeModule();

  // If the user is making use of obsolete varargs intrinsics, adjust them for
  // the user.
  if (Function *F = M->getNamedFunction("llvm.va_start")) {
    assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!");

    const Type *RetTy = F->getFunctionType()->getParamType(0);
    RetTy = cast<PointerType>(RetTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_start", RetTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_end")) {
    assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_end", Type::VoidTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new LoadInst(CI->getOperand(1), "", CI);
        new CallInst(NF, V, "", CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_copy")) {
    assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_copy", ArgTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, CI->getOperand(2), "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }
  return MP;
}

//===----------------------------------------------------------------------===//
// Wrapper functions
//===----------------------------------------------------------------------===//

/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
/// buffer
ModuleProvider*
getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
                                const std::string &ModuleID) {
  return CheckVarargs(new BytecodeBufferReader(Buffer, Length, ModuleID));
}

/// ParseBytecodeBuffer - Parse a given bytecode buffer
///
Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
                            const std::string &ModuleID, std::string *ErrorStr){
  try {
    std::auto_ptr<ModuleProvider>
      AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
///
ModuleProvider *getBytecodeModuleProvider(const std::string &Filename) {
  if (Filename != std::string("-"))        // Read from a file...
    return CheckVarargs(new BytecodeFileReader(Filename));
  else                                     // Read from stdin
    return CheckVarargs(new BytecodeStdinReader());
}

/// ParseBytecodeFile - Parse the given bytecode file
///
Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
  try {
    std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

} // End llvm namespace
<commit_msg>Fine grainify namespacification, #include file that defines the interface!<commit_after>//===- ReaderWrappers.cpp - Parse bytecode from file or buffer  -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements loading and parsing a bytecode file and parsing a
// bytecode module from a given buffer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Bytecode/Reader.h"
#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "Support/StringExtras.h"
#include "Config/fcntl.h"
#include <sys/stat.h>
#include "Config/unistd.h"
#include "Config/sys/mman.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// BytecodeFileReader - Read from an mmap'able file descriptor.
//

namespace {
  /// FDHandle - Simple handle class to make sure a file descriptor gets closed
  /// when the object is destroyed.
  ///
  class FDHandle {
    int FD;
  public:
    FDHandle(int fd) : FD(fd) {}
    operator int() const { return FD; }
    ~FDHandle() {
      if (FD != -1) close(FD);
    }
  };

  /// BytecodeFileReader - parses a bytecode file from a file
  ///
  class BytecodeFileReader : public BytecodeParser {
  private:
    unsigned char *Buffer;
    int Length;

    BytecodeFileReader(const BytecodeFileReader&); // Do not implement
    void operator=(const BytecodeFileReader &BFR); // Do not implement

  public:
    BytecodeFileReader(const std::string &Filename);
    ~BytecodeFileReader();
  };
}

BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
  FDHandle FD = open(Filename.c_str(), O_RDONLY);
  if (FD == -1)
    throw std::string("Error opening file!");

  // Stat the file to get its length...
  struct stat StatBuf;
  if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
    throw std::string("Error stat'ing file!");

  // mmap in the file all at once...
  Length = StatBuf.st_size;
  Buffer = (unsigned char*)mmap(0, Length, PROT_READ, MAP_PRIVATE, FD, 0);

  if (Buffer == (unsigned char*)MAP_FAILED)
    throw std::string("Error mmapping file!");

  try {
    // Parse the bytecode we mmapped in
    ParseBytecode(Buffer, Length, Filename);
  } catch (...) {
    munmap((char*)Buffer, Length);
    throw;
  }
}

BytecodeFileReader::~BytecodeFileReader() {
  // Unmmap the bytecode...
  munmap((char*)Buffer, Length);
}

//===----------------------------------------------------------------------===//
// BytecodeBufferReader - Read from a memory buffer
//

namespace {
  /// BytecodeBufferReader - parses a bytecode file from a buffer
  ///
  class BytecodeBufferReader : public BytecodeParser {
  private:
    const unsigned char *Buffer;
    bool MustDelete;

    BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement
    void operator=(const BytecodeBufferReader &BFR);   // Do not implement

  public:
    BytecodeBufferReader(const unsigned char *Buf, unsigned Length,
                         const std::string &ModuleID);
    ~BytecodeBufferReader();

  };
}

BytecodeBufferReader::BytecodeBufferReader(const unsigned char *Buf,
                                           unsigned Length,
                                           const std::string &ModuleID)
{
  // If not aligned, allocate a new buffer to hold the bytecode...
  const unsigned char *ParseBegin = 0;
  if ((intptr_t)Buf & 3) {
    Buffer = new unsigned char[Length+4];
    unsigned Offset = 4 - ((intptr_t)Buffer & 3);   // Make sure it's aligned
    ParseBegin = Buffer + Offset;
    memcpy((unsigned char*)ParseBegin, Buf, Length);    // Copy it over
    MustDelete = true;
  } else {
    // If we don't need to copy it over, just use the caller's copy
    ParseBegin = Buffer = Buf;
    MustDelete = false;
  }
  try {
    ParseBytecode(ParseBegin, Length, ModuleID);
  } catch (...) {
    if (MustDelete) delete [] Buffer;
    throw;
  }
}

BytecodeBufferReader::~BytecodeBufferReader() {
  if (MustDelete) delete [] Buffer;
}

//===----------------------------------------------------------------------===//
//  BytecodeStdinReader - Read bytecode from Standard Input
//

namespace {
  /// BytecodeStdinReader - parses a bytecode file from stdin
  ///
  class BytecodeStdinReader : public BytecodeParser {
  private:
    std::vector<unsigned char> FileData;
    unsigned char *FileBuf;

    BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
    void operator=(const BytecodeStdinReader &BFR);  // Do not implement

  public:
    BytecodeStdinReader();
  };
}

BytecodeStdinReader::BytecodeStdinReader() {
  int BlockSize;
  unsigned char Buffer[4096*4];

  // Read in all of the data from stdin, we cannot mmap stdin...
  while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) {
    if (BlockSize == -1)
      throw std::string("Error reading from stdin!");

    FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
  }

  if (FileData.empty())
    throw std::string("Standard Input empty!");

  FileBuf = &FileData[0];
  ParseBytecode(FileBuf, FileData.size(), "<stdin>");
}

//===----------------------------------------------------------------------===//
//  Varargs transmogrification code...
//

// CheckVarargs - This is used to automatically translate old-style varargs to
// new style varargs for backwards compatibility.
static ModuleProvider *CheckVarargs(ModuleProvider *MP) {
  Module *M = MP->getModule();

  // Check to see if va_start takes arguments...
  Function *F = M->getNamedFunction("llvm.va_start");
  if (F == 0) return MP;  // No varargs use, just return.

  if (F->getFunctionType()->getNumParams() == 0)
    return MP;  // Modern varargs processing, just return.

  // If we get to this point, we know that we have an old-style module.
  // Materialize the whole thing to perform the rewriting.
  MP->materializeModule();

  // If the user is making use of obsolete varargs intrinsics, adjust them for
  // the user.
  if (Function *F = M->getNamedFunction("llvm.va_start")) {
    assert(F->asize() == 1 && "Obsolete va_start takes 1 argument!");

    const Type *RetTy = F->getFunctionType()->getParamType(0);
    RetTy = cast<PointerType>(RetTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_start", RetTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_end")) {
    assert(F->asize() == 1 && "Obsolete va_end takes 1 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_end", Type::VoidTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new LoadInst(CI->getOperand(1), "", CI);
        new CallInst(NF, V, "", CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }

  if (Function *F = M->getNamedFunction("llvm.va_copy")) {
    assert(F->asize() == 2 && "Obsolete va_copy takes 2 argument!");
    const Type *ArgTy = F->getFunctionType()->getParamType(0);
    ArgTy = cast<PointerType>(ArgTy)->getElementType();
    Function *NF = M->getOrInsertFunction("llvm.va_copy", ArgTy,
                                                  ArgTy, 0);

    for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; )
      if (CallInst *CI = dyn_cast<CallInst>(*I++)) {
        Value *V = new CallInst(NF, CI->getOperand(2), "", CI);
        new StoreInst(V, CI->getOperand(1), CI);
        CI->getParent()->getInstList().erase(CI);
      }
    F->setName("");
  }
  return MP;
}

//===----------------------------------------------------------------------===//
// Wrapper functions
//===----------------------------------------------------------------------===//

/// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a
/// buffer
ModuleProvider*
llvm::getBytecodeBufferModuleProvider(const unsigned char *Buffer,
                                      unsigned Length,
                                      const std::string &ModuleID) {
  return CheckVarargs(new BytecodeBufferReader(Buffer, Length, ModuleID));
}

/// ParseBytecodeBuffer - Parse a given bytecode buffer
///
Module *llvm::ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
                                  const std::string &ModuleID,
                                  std::string *ErrorStr){
  try {
    std::auto_ptr<ModuleProvider>
      AMP(getBytecodeBufferModuleProvider(Buffer, Length, ModuleID));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

/// getBytecodeModuleProvider - lazy function-at-a-time loading from a file
///
ModuleProvider *llvm::getBytecodeModuleProvider(const std::string &Filename) {
  if (Filename != std::string("-"))        // Read from a file...
    return CheckVarargs(new BytecodeFileReader(Filename));
  else                                     // Read from stdin
    return CheckVarargs(new BytecodeStdinReader());
}

/// ParseBytecodeFile - Parse the given bytecode file
///
Module *llvm::ParseBytecodeFile(const std::string &Filename,
                                std::string *ErrorStr) {
  try {
    std::auto_ptr<ModuleProvider> AMP(getBytecodeModuleProvider(Filename));
    return AMP->releaseModule();
  } catch (std::string &err) {
    if (ErrorStr) *ErrorStr = err;
    return 0;
  }
}

<|endoftext|>


<commit_before>//=== LLVMConventionsChecker.cpp - Check LLVM codebase conventions ---*- C++ -*-
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines LLVMConventionsChecker, a bunch of small little checks
// for checking specific coding conventions in the LLVM/Clang codebase.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Checker/Checkers/LocalCheckers.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include <string>
#include <llvm/ADT/StringRef.h>

using namespace clang;

//===----------------------------------------------------------------------===//
// Generic type checking routines.
//===----------------------------------------------------------------------===//

static bool IsStringRef(QualType T) {
  const RecordType *RT = T->getAs<RecordType>();
  if (!RT)
    return false;

  return llvm::StringRef(QualType(RT, 0).getAsString()) ==
  "class llvm::StringRef";
}

static bool IsStdString(QualType T) {
  if (const QualifiedNameType *QT = T->getAs<QualifiedNameType>())
    T = QT->getNamedType();

  const TypedefType *TT = T->getAs<TypedefType>();
  if (!TT)
    return false;

  const TypedefDecl *TD = TT->getDecl();
  const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(TD->getDeclContext());
  if (!ND)
    return false;
  const IdentifierInfo *II = ND->getIdentifier();
  if (!II || II->getName() != "std")
    return false;

  DeclarationName N = TD->getDeclName();
  return llvm::StringRef(N.getAsString()) == "string";
}

//===----------------------------------------------------------------------===//
// CHECK: a llvm::StringRef should not be bound to a temporary std::string whose
// lifetime is shorter than the StringRef's.
//===----------------------------------------------------------------------===//

namespace {
class StringRefCheckerVisitor : public StmtVisitor<StringRefCheckerVisitor> {
  BugReporter &BR;
public:
  StringRefCheckerVisitor(BugReporter &br) : BR(br) {}
  void VisitChildren(Stmt *S) {
    for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
      I != E; ++I)
      if (Stmt *child = *I)
        Visit(child);
  }
  void VisitStmt(Stmt *S) { VisitChildren(S); }
  void VisitDeclStmt(DeclStmt *DS);
private:
  void VisitVarDecl(VarDecl *VD);
};
} // end anonymous namespace

static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR) {
  StringRefCheckerVisitor walker(BR);
  walker.Visit(D->getBody());
}

void StringRefCheckerVisitor::VisitDeclStmt(DeclStmt *S) {
  for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();I!=E; ++I)
    if (VarDecl *VD = dyn_cast<VarDecl>(*I))
      VisitVarDecl(VD);
}

void StringRefCheckerVisitor::VisitVarDecl(VarDecl *VD) {
  Expr *Init = VD->getInit();
  if (!Init)
    return;

  // Pattern match for:
  // llvm::StringRef x = call() (where call returns std::string)
  if (!IsStringRef(VD->getType()))
    return;
  CXXExprWithTemporaries *Ex1 = dyn_cast<CXXExprWithTemporaries>(Init);
  if (!Ex1)
    return;
  CXXConstructExpr *Ex2 = dyn_cast<CXXConstructExpr>(Ex1->getSubExpr());
  if (!Ex2 || Ex2->getNumArgs() != 1)
    return;
  ImplicitCastExpr *Ex3 = dyn_cast<ImplicitCastExpr>(Ex2->getArg(0));
  if (!Ex3)
    return;
  CXXConstructExpr *Ex4 = dyn_cast<CXXConstructExpr>(Ex3->getSubExpr());
  if (!Ex4 || Ex4->getNumArgs() != 1)
    return;
  ImplicitCastExpr *Ex5 = dyn_cast<ImplicitCastExpr>(Ex4->getArg(0));
  if (!Ex5)
    return;
  CXXBindTemporaryExpr *Ex6 = dyn_cast<CXXBindTemporaryExpr>(Ex5->getSubExpr());
  if (!Ex6 || !IsStdString(Ex6->getType()))
    return;

  // Okay, badness!  Report an error.
  BR.EmitBasicReport("StringRef should not be bound to temporary "
                     "std::string that it outlives", "LLVM Conventions",
                     VD->getLocStart(), Init->getSourceRange());
}

//===----------------------------------------------------------------------===//
// Entry point for all checks.
//===----------------------------------------------------------------------===//

void clang::CheckLLVMConventions(const Decl *D, BugReporter &BR) {
  CheckStringRefAssignedTemporary(D, BR);
}
<commit_msg>For the StringRef check, also visit the children of DeclStmts.<commit_after>//=== LLVMConventionsChecker.cpp - Check LLVM codebase conventions ---*- C++ -*-
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines LLVMConventionsChecker, a bunch of small little checks
// for checking specific coding conventions in the LLVM/Clang codebase.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Checker/Checkers/LocalCheckers.h"
#include "clang/Checker/BugReporter/BugReporter.h"
#include <string>
#include <llvm/ADT/StringRef.h>

using namespace clang;

//===----------------------------------------------------------------------===//
// Generic type checking routines.
//===----------------------------------------------------------------------===//

static bool IsStringRef(QualType T) {
  const RecordType *RT = T->getAs<RecordType>();
  if (!RT)
    return false;

  return llvm::StringRef(QualType(RT, 0).getAsString()) ==
  "class llvm::StringRef";
}

static bool IsStdString(QualType T) {
  if (const QualifiedNameType *QT = T->getAs<QualifiedNameType>())
    T = QT->getNamedType();

  const TypedefType *TT = T->getAs<TypedefType>();
  if (!TT)
    return false;

  const TypedefDecl *TD = TT->getDecl();
  const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(TD->getDeclContext());
  if (!ND)
    return false;
  const IdentifierInfo *II = ND->getIdentifier();
  if (!II || II->getName() != "std")
    return false;

  DeclarationName N = TD->getDeclName();
  return llvm::StringRef(N.getAsString()) == "string";
}

//===----------------------------------------------------------------------===//
// CHECK: a llvm::StringRef should not be bound to a temporary std::string whose
// lifetime is shorter than the StringRef's.
//===----------------------------------------------------------------------===//

namespace {
class StringRefCheckerVisitor : public StmtVisitor<StringRefCheckerVisitor> {
  BugReporter &BR;
public:
  StringRefCheckerVisitor(BugReporter &br) : BR(br) {}
  void VisitChildren(Stmt *S) {
    for (Stmt::child_iterator I = S->child_begin(), E = S->child_end() ;
      I != E; ++I)
      if (Stmt *child = *I)
        Visit(child);
  }
  void VisitStmt(Stmt *S) { VisitChildren(S); }
  void VisitDeclStmt(DeclStmt *DS);
private:
  void VisitVarDecl(VarDecl *VD);
  void CheckStringRefBoundtoTemporaryString(VarDecl *VD);
};
} // end anonymous namespace

static void CheckStringRefAssignedTemporary(const Decl *D, BugReporter &BR) {
  StringRefCheckerVisitor walker(BR);
  walker.Visit(D->getBody());
}

void StringRefCheckerVisitor::VisitDeclStmt(DeclStmt *S) {
  VisitChildren(S);

  for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();I!=E; ++I)
    if (VarDecl *VD = dyn_cast<VarDecl>(*I))
      VisitVarDecl(VD);
}

void StringRefCheckerVisitor::VisitVarDecl(VarDecl *VD) {
  Expr *Init = VD->getInit();
  if (!Init)
    return;

  // Pattern match for:
  // llvm::StringRef x = call() (where call returns std::string)
  if (!IsStringRef(VD->getType()))
    return;
  CXXExprWithTemporaries *Ex1 = dyn_cast<CXXExprWithTemporaries>(Init);
  if (!Ex1)
    return;
  CXXConstructExpr *Ex2 = dyn_cast<CXXConstructExpr>(Ex1->getSubExpr());
  if (!Ex2 || Ex2->getNumArgs() != 1)
    return;
  ImplicitCastExpr *Ex3 = dyn_cast<ImplicitCastExpr>(Ex2->getArg(0));
  if (!Ex3)
    return;
  CXXConstructExpr *Ex4 = dyn_cast<CXXConstructExpr>(Ex3->getSubExpr());
  if (!Ex4 || Ex4->getNumArgs() != 1)
    return;
  ImplicitCastExpr *Ex5 = dyn_cast<ImplicitCastExpr>(Ex4->getArg(0));
  if (!Ex5)
    return;
  CXXBindTemporaryExpr *Ex6 = dyn_cast<CXXBindTemporaryExpr>(Ex5->getSubExpr());
  if (!Ex6 || !IsStdString(Ex6->getType()))
    return;

  // Okay, badness!  Report an error.
  BR.EmitBasicReport("StringRef should not be bound to temporary "
                     "std::string that it outlives", "LLVM Conventions",
                     VD->getLocStart(), Init->getSourceRange());
}

//===----------------------------------------------------------------------===//
// Entry point for all checks.
//===----------------------------------------------------------------------===//

void clang::CheckLLVMConventions(const Decl *D, BugReporter &BR) {
  CheckStringRefAssignedTemporary(D, BR);
}
<|endoftext|>


<commit_before>//===-- sanitizer_common.cc -----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries.
//===----------------------------------------------------------------------===//

#include "sanitizer_common.h"
#include "sanitizer_libc.h"

namespace __sanitizer {

uptr GetPageSizeCached() {
  static uptr PageSize;
  if (!PageSize)
    PageSize = GetPageSize();
  return PageSize;
}

// By default, dump to stderr. If report_fd is kInvalidFd, try to obtain file
// descriptor by opening file in report_path.
static fd_t report_fd = kStderrFd;
static char report_path[4096];  // Set via __sanitizer_set_report_path.

static void (*DieCallback)(void);
void SetDieCallback(void (*callback)(void)) {
  DieCallback = callback;
}

void NORETURN Die() {
  if (DieCallback) {
    DieCallback();
  }
  Exit(1);
}

static CheckFailedCallbackType CheckFailedCallback;
void SetCheckFailedCallback(CheckFailedCallbackType callback) {
  CheckFailedCallback = callback;
}

void NORETURN CheckFailed(const char *file, int line, const char *cond,
                          u64 v1, u64 v2) {
  if (CheckFailedCallback) {
    CheckFailedCallback(file, line, cond, v1, v2);
  }
  Report("Sanitizer CHECK failed: %s:%d %s (%zd, %zd)\n", file, line, cond,
                                                          v1, v2);
  Die();
}

static void MaybeOpenReportFile() {
  if (report_fd != kInvalidFd)
    return;
  fd_t fd = internal_open(report_path, true);
  if (fd == kInvalidFd) {
    report_fd = kStderrFd;
    Report("ERROR: Can't open file: %s\n", report_path);
    Die();
  }
  report_fd = fd;
}

bool PrintsToTty() {
  MaybeOpenReportFile();
  return internal_isatty(report_fd);
}

void RawWrite(const char *buffer) {
  static const char *kRawWriteError = "RawWrite can't output requested buffer!";
  uptr length = (uptr)internal_strlen(buffer);
  MaybeOpenReportFile();
  if (length != internal_write(report_fd, buffer, length)) {
    internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
    Die();
  }
}

uptr ReadFileToBuffer(const char *file_name, char **buff,
                      uptr *buff_size, uptr max_len) {
  uptr PageSize = GetPageSizeCached();
  uptr kMinFileLen = PageSize;
  uptr read_len = 0;
  *buff = 0;
  *buff_size = 0;
  // The files we usually open are not seekable, so try different buffer sizes.
  for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
    fd_t fd = internal_open(file_name, /*write*/ false);
    if (fd == kInvalidFd) return 0;
    UnmapOrDie(*buff, *buff_size);
    *buff = (char*)MmapOrDie(size, __FUNCTION__);
    *buff_size = size;
    // Read up to one page at a time.
    read_len = 0;
    bool reached_eof = false;
    while (read_len + PageSize <= size) {
      uptr just_read = internal_read(fd, *buff + read_len, PageSize);
      if (just_read == 0) {
        reached_eof = true;
        break;
      }
      read_len += just_read;
    }
    internal_close(fd);
    if (reached_eof)  // We've read the whole file.
      break;
  }
  return read_len;
}

// We don't want to use std::sort to avoid including <algorithm>, as
// we may end up with two implementation of std::sort - one in instrumented
// code, and the other in runtime.
// qsort() from stdlib won't work as it calls malloc(), which results
// in deadlock in ASan allocator.
// We re-implement in-place sorting w/o recursion as straightforward heapsort.
void SortArray(uptr *array, uptr size) {
  if (size < 2)
    return;
  // Stage 1: insert elements to the heap.
  for (uptr i = 1; i < size; i++) {
    uptr j, p;
    for (j = i; j > 0; j = p) {
      p = (j - 1) / 2;
      if (array[j] > array[p])
        Swap(array[j], array[p]);
      else
        break;
    }
  }
  // Stage 2: swap largest element with the last one,
  // and sink the new top.
  for (uptr i = size - 1; i > 0; i--) {
    Swap(array[0], array[i]);
    uptr j, max_ind;
    for (j = 0; j < i; j = max_ind) {
      uptr left = 2 * j + 1;
      uptr right = 2 * j + 2;
      max_ind = j;
      if (left < i && array[left] > array[max_ind])
        max_ind = left;
      if (right < i && array[right] > array[max_ind])
        max_ind = right;
      if (max_ind != j)
        Swap(array[j], array[max_ind]);
      else
        break;
    }
  }
}

// We want to map a chunk of address space aligned to 'alignment'.
// We do it by maping a bit more and then unmaping redundant pieces.
// We probably can do it with fewer syscalls in some OS-dependent way.
void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) {
// uptr PageSize = GetPageSizeCached();
  CHECK(IsPowerOfTwo(size));
  CHECK(IsPowerOfTwo(alignment));
  uptr map_size = size + alignment;
  uptr map_res = (uptr)MmapOrDie(map_size, mem_type);
  uptr map_end = map_res + map_size;
  uptr res = map_res;
  if (res & (alignment - 1))  // Not aligned.
    res = (map_res + alignment) & ~(alignment - 1);
  uptr end = res + size;
  if (res != map_res)
    UnmapOrDie((void*)map_res, res - map_res);
  if (end != map_end)
    UnmapOrDie((void*)end, map_end - end);
  return (void*)res;
}

}  // namespace __sanitizer

using namespace __sanitizer;  // NOLINT

extern "C" {
void __sanitizer_set_report_path(const char *path) {
  if (!path) return;
  uptr len = internal_strlen(path);
  if (len > sizeof(report_path) - 100) {
    Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
           path[0], path[1], path[2], path[3],
           path[4], path[5], path[6], path[7]);
    Die();
  }
  internal_snprintf(report_path, sizeof(report_path), "%s.%d", path, GetPid());
  report_fd = kInvalidFd;
}

void __sanitizer_set_report_fd(int fd) {
  if (report_fd != kStdoutFd &&
      report_fd != kStderrFd &&
      report_fd != kInvalidFd)
    internal_close(report_fd);
  report_fd = fd;
}

void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) {
  (void)reserved;
  PrepareForSandboxing();
}
}  // extern "C"
<commit_msg>asan: fix format string in CHECK<commit_after>//===-- sanitizer_common.cc -----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between AddressSanitizer and ThreadSanitizer
// run-time libraries.
//===----------------------------------------------------------------------===//

#include "sanitizer_common.h"
#include "sanitizer_libc.h"

namespace __sanitizer {

uptr GetPageSizeCached() {
  static uptr PageSize;
  if (!PageSize)
    PageSize = GetPageSize();
  return PageSize;
}

// By default, dump to stderr. If report_fd is kInvalidFd, try to obtain file
// descriptor by opening file in report_path.
static fd_t report_fd = kStderrFd;
static char report_path[4096];  // Set via __sanitizer_set_report_path.

static void (*DieCallback)(void);
void SetDieCallback(void (*callback)(void)) {
  DieCallback = callback;
}

void NORETURN Die() {
  if (DieCallback) {
    DieCallback();
  }
  Exit(1);
}

static CheckFailedCallbackType CheckFailedCallback;
void SetCheckFailedCallback(CheckFailedCallbackType callback) {
  CheckFailedCallback = callback;
}

void NORETURN CheckFailed(const char *file, int line, const char *cond,
                          u64 v1, u64 v2) {
  if (CheckFailedCallback) {
    CheckFailedCallback(file, line, cond, v1, v2);
  }
  Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file, line, cond,
                                                            v1, v2);
  Die();
}

static void MaybeOpenReportFile() {
  if (report_fd != kInvalidFd)
    return;
  fd_t fd = internal_open(report_path, true);
  if (fd == kInvalidFd) {
    report_fd = kStderrFd;
    Report("ERROR: Can't open file: %s\n", report_path);
    Die();
  }
  report_fd = fd;
}

bool PrintsToTty() {
  MaybeOpenReportFile();
  return internal_isatty(report_fd);
}

void RawWrite(const char *buffer) {
  static const char *kRawWriteError = "RawWrite can't output requested buffer!";
  uptr length = (uptr)internal_strlen(buffer);
  MaybeOpenReportFile();
  if (length != internal_write(report_fd, buffer, length)) {
    internal_write(report_fd, kRawWriteError, internal_strlen(kRawWriteError));
    Die();
  }
}

uptr ReadFileToBuffer(const char *file_name, char **buff,
                      uptr *buff_size, uptr max_len) {
  uptr PageSize = GetPageSizeCached();
  uptr kMinFileLen = PageSize;
  uptr read_len = 0;
  *buff = 0;
  *buff_size = 0;
  // The files we usually open are not seekable, so try different buffer sizes.
  for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
    fd_t fd = internal_open(file_name, /*write*/ false);
    if (fd == kInvalidFd) return 0;
    UnmapOrDie(*buff, *buff_size);
    *buff = (char*)MmapOrDie(size, __FUNCTION__);
    *buff_size = size;
    // Read up to one page at a time.
    read_len = 0;
    bool reached_eof = false;
    while (read_len + PageSize <= size) {
      uptr just_read = internal_read(fd, *buff + read_len, PageSize);
      if (just_read == 0) {
        reached_eof = true;
        break;
      }
      read_len += just_read;
    }
    internal_close(fd);
    if (reached_eof)  // We've read the whole file.
      break;
  }
  return read_len;
}

// We don't want to use std::sort to avoid including <algorithm>, as
// we may end up with two implementation of std::sort - one in instrumented
// code, and the other in runtime.
// qsort() from stdlib won't work as it calls malloc(), which results
// in deadlock in ASan allocator.
// We re-implement in-place sorting w/o recursion as straightforward heapsort.
void SortArray(uptr *array, uptr size) {
  if (size < 2)
    return;
  // Stage 1: insert elements to the heap.
  for (uptr i = 1; i < size; i++) {
    uptr j, p;
    for (j = i; j > 0; j = p) {
      p = (j - 1) / 2;
      if (array[j] > array[p])
        Swap(array[j], array[p]);
      else
        break;
    }
  }
  // Stage 2: swap largest element with the last one,
  // and sink the new top.
  for (uptr i = size - 1; i > 0; i--) {
    Swap(array[0], array[i]);
    uptr j, max_ind;
    for (j = 0; j < i; j = max_ind) {
      uptr left = 2 * j + 1;
      uptr right = 2 * j + 2;
      max_ind = j;
      if (left < i && array[left] > array[max_ind])
        max_ind = left;
      if (right < i && array[right] > array[max_ind])
        max_ind = right;
      if (max_ind != j)
        Swap(array[j], array[max_ind]);
      else
        break;
    }
  }
}

// We want to map a chunk of address space aligned to 'alignment'.
// We do it by maping a bit more and then unmaping redundant pieces.
// We probably can do it with fewer syscalls in some OS-dependent way.
void *MmapAlignedOrDie(uptr size, uptr alignment, const char *mem_type) {
// uptr PageSize = GetPageSizeCached();
  CHECK(IsPowerOfTwo(size));
  CHECK(IsPowerOfTwo(alignment));
  uptr map_size = size + alignment;
  uptr map_res = (uptr)MmapOrDie(map_size, mem_type);
  uptr map_end = map_res + map_size;
  uptr res = map_res;
  if (res & (alignment - 1))  // Not aligned.
    res = (map_res + alignment) & ~(alignment - 1);
  uptr end = res + size;
  if (res != map_res)
    UnmapOrDie((void*)map_res, res - map_res);
  if (end != map_end)
    UnmapOrDie((void*)end, map_end - end);
  return (void*)res;
}

}  // namespace __sanitizer

using namespace __sanitizer;  // NOLINT

extern "C" {
void __sanitizer_set_report_path(const char *path) {
  if (!path) return;
  uptr len = internal_strlen(path);
  if (len > sizeof(report_path) - 100) {
    Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n",
           path[0], path[1], path[2], path[3],
           path[4], path[5], path[6], path[7]);
    Die();
  }
  internal_snprintf(report_path, sizeof(report_path), "%s.%d", path, GetPid());
  report_fd = kInvalidFd;
}

void __sanitizer_set_report_fd(int fd) {
  if (report_fd != kStdoutFd &&
      report_fd != kStderrFd &&
      report_fd != kInvalidFd)
    internal_close(report_fd);
  report_fd = fd;
}

void NOINLINE __sanitizer_sandbox_on_notify(void *reserved) {
  (void)reserved;
  PrepareForSandboxing();
}
}  // extern "C"
<|endoftext|>