<commit_before>/*
  ePaper.cpp
  2013 Copyright (c) Seeed Technology Inc.  All right reserved.

  Modified by Loovee
  www.seeedstudio.com
  2013-7-2

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <Arduino.h>
#include <SPI.h>
#include "GT20L16_drive.h"
#include "ePaper.h"

static void spi_on()
{
    SPI.begin();
    //SPI.setClockDivider(SPI_CLOCK_DIV2);
    //SPI_put(0x00);
    //SPI_put(0x00);
}

/*********************************************************************************************************
* \brief According to EPD size and temperature to get stage_time
* \note Refer to COG document Section 5.3 for more details
*
* \param EPD_type_index The defined EPD size
**********************************************************************************************************/
void ePaper::begin(EPD_size sz)
{
    size = sz;
    direction = DIRNORMAL;

    DISP_LEN    = 200;
    DISP_WIDTH  = 96;

    EPD.begin(size);
    init_io();
}

/*********************************************************************************************************
** Function name:           start
** Descriptions:            start
*********************************************************************************************************/
void ePaper::start()
{
    EPD.start();
}

/*********************************************************************************************************
** Function name:           end
** Descriptions:            end
*********************************************************************************************************/
void ePaper::end()
{
    EPD.end();
}

/*********************************************************************************************************
** Function name:           init_io
** Descriptions:            init IO
*********************************************************************************************************/
void ePaper::init_io()
{
    // init IO
    pinMode(Pin_BUSY, INPUT);
    pinMode(Pin_RESET, OUTPUT);
    pinMode(Pin_PANEL_ON, OUTPUT);
    pinMode(Pin_DISCHARGE, OUTPUT);
    pinMode(Pin_BORDER, OUTPUT);
    pinMode(Pin_EPD_CS, OUTPUT);
    pinMode(Pin_SD_CS, OUTPUT);

    pinMode(9, OUTPUT);
    digitalWrite(9, HIGH);

    digitalWrite(Pin_RESET, LOW);
    digitalWrite(Pin_PANEL_ON, LOW);
    digitalWrite(Pin_DISCHARGE, LOW);
    digitalWrite(Pin_BORDER, LOW);
    digitalWrite(Pin_EPD_CS, HIGH);
    digitalWrite(Pin_SD_CS, HIGH);

    // init SPI
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
    //SPI.setClockDivider(SPI_CLOCK_DIV2);
}

/*********************************************************************************************************
** Function name:           drawUnicode
** Descriptions:            draw a unicode
*********************************************************************************************************/
int ePaper::drawUnicode(unsigned int uniCode, int x, int y)
{

   // if(((x+16)>= DISP_LEN) || ((y+16) >= DISP_WIDTH) || x<0 || y<0) return 0;

    int dtaLen = GT20L16.getMatrixUnicode(uniCode, tMatrix);

    int pX      = 0;
    int pY      = 0;
    int color   = 0;
    //spi_on();
    for(int k = 0; k<2; k++)
    {
        for(int i=0; i<8; i++)
        {
            for(int j=0; j<(dtaLen/2); j++)
            {

                if(tMatrix[j+(dtaLen/2)*k] & (0x01<<(7-i)))
                {
                    color = 1;
                }
                else
                {
                    color = 0;
                }

                pX = x + j;
                pY = y + k*8+i;

                drawPixel(pX, pY, color);
            }
        }
    }

    return dtaLen/2;        // x +
}

int ePaper::drawUnicode(unsigned char *matrix, int x, int y)
{

   // if(((x+16)>= DISP_LEN) || ((y+16) >= DISP_WIDTH) || x<0 || y<0) return 0;

    int dtaLen  = 32;
    int pX      = 0;
    int pY      = 0;
    int color   = 0;
    //spi_on();
    for(int k = 0; k<2; k++)
    {
        for(int i=0; i<8; i++)
        {
            for(int j=0; j<(dtaLen/2); j++)
            {

                if(matrix[j+(dtaLen/2)*k] & (0x01<<(7-i)))
                {
                    color = 1;
                }
                else
                {
                    color = 0;
                }

                pX = x + j;
                pY = y + k*8+i;

                drawPixel(pX, pY, color);
            }
        }
    }

    return dtaLen/2;        // x +
}

/*********************************************************************************************************
** Function name:           drawUnicodeString
** Descriptions:            draw string
*********************************************************************************************************/
int ePaper::drawUnicodeString(unsigned int *uniCode, int len, int x, int y)
{
    int xPlus = 0;
    int xSum  = 0;

    for(int i=0; i<len; i++)
    {
        xPlus = drawUnicode(uniCode[i], x, y);
        x += xPlus;
        xSum += xPlus;
    }
    return xSum;
}

/*********************************************************************************************************
** Function name:           drawChar
** Descriptions:            draw char
*********************************************************************************************************/
int ePaper::drawChar(char c, int x, int y)
{
    return drawUnicode(c, x, y);
}

/*********************************************************************************************************
** Function name:           drawString
** Descriptions:            draw string
*********************************************************************************************************/
int ePaper::drawString(char *string, int poX, int poY)
{
    int sumX = 0;

    while(*string)
    {

        int xPlus = drawChar(*string, poX, poY);
        sumX += xPlus;
        *string++;

        if(poX < 200)
        {
            poX += xPlus;                                     /* Move cursor right            */
        }
    }

    return sumX;
}

/*********************************************************************************************************
** Function name:           drawNumber
** Descriptions:            drawNumber
*********************************************************************************************************/
int ePaper::drawNumber(long long_num,int poX, int poY)
{
    char tmp[10];
    sprintf(tmp, "%d", long_num);
    return drawString(tmp, poX, poY);

}

/*********************************************************************************************************
** Function name:           drawFloat
** Descriptions:            drawFloat
*********************************************************************************************************/
int ePaper::drawFloat(float floatNumber, int decimal, int poX, int poY)
{
    unsigned long temp=0;
    float decy=0.0;
    float rounding = 0.5;
    unsigned char f=0;

    float eep = 0.000001;

    int sumX    = 0;
    int xPlus   = 0;

    if(floatNumber-0.0 < eep)       // floatNumber < 0
    {
        xPlus = drawChar('-',poX, poY);
        floatNumber = -floatNumber;

        poX  += xPlus;
        sumX += xPlus;
    }

    for (unsigned char i=0; i<decimal; ++i)
    {
        rounding /= 10.0;
    }

    floatNumber += rounding;

    temp = (long)floatNumber;

    xPlus = drawNumber(temp,poX, poY);

    poX  += xPlus;
    sumX += xPlus;

    if(decimal>0)
    {
        xPlus = drawChar('.',poX, poY);
        poX += xPlus;                                       /* Move cursor right            */
        sumX += xPlus;
    }
    else
    {
        return sumX;
    }

    decy = floatNumber - temp;
    for(unsigned char i=0; i<decimal; i++)
    {
        decy *= 10;                                                      /* for the next decimal         */
        temp = decy;                                                    /* get the decimal              */
        xPlus = drawNumber(temp,poX, poY);

        poX += xPlus;                                       /* Move cursor right            */
        sumX += xPlus;
        decy -= temp;
    }
    return sumX;
}

/*********************************************************************************************************
** Function name:           drawLine
** Descriptions:            drawLine
*********************************************************************************************************/
void ePaper::drawLine(int x0, int y0, int x1, int y1)
{

    init_io();

    int x = x1-x0;
    int y = y1-y0;
    int dx = abs(x), sx = x0<x1 ? 1 : -1;
    int dy = -abs(y), sy = y0<y1 ? 1 : -1;
    int err = dx+dy, e2;
    for (;;)
    {
        drawPixel(x0,y0,1);
        e2 = 2*err;
        if (e2 >= dy)
        {
            if (x0 == x1) break;
            err += dy; x0 += sx;
        }
        if (e2 <= dx)
        {
            if (y0 == y1) break;
            err += dx; y0 += sy;
        }
    }
}

/*********************************************************************************************************
** Function name:           clear_sd
** Descriptions:            clear sd card
*********************************************************************************************************/
void ePaper::clear_sd()
{

    init_io();

    for(int i=0; i<DISP_WIDTH; i++)
    {
        for(int j=0; j<DISP_LEN; j++)
        {
            drawPixel(j, i, 0);

        }
    }
}

/*********************************************************************************************************
** Function name:           drawCircle
** Descriptions:            drawCircle
*********************************************************************************************************/
void ePaper::drawCircle(int poX, int poY, int r)
{

    init_io();
    int x = -r, y = 0, err = 2-2*r, e2;
    do {
        drawPixel(poX-x, poY+y, 1);
        drawPixel(poX+x, poY+y, 1);
        drawPixel(poX+x, poY-y, 1);
        drawPixel(poX-x, poY-y, 1);
        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);
}

/*********************************************************************************************************
** Function name:           drawHorizontalLine
** Descriptions:            drawHorizontalLine
*********************************************************************************************************/
void ePaper::drawHorizontalLine( int poX, int poY, int len)
{
    drawLine(poX, poY, poX+len, poY);
}

/*********************************************************************************************************
** Function name:           drawVerticalLine
** Descriptions:            drawVerticalLine
*********************************************************************************************************/
void ePaper::drawVerticalLine( int poX, int poY, int len)
{
    drawLine(poX, poY, poX, poY+len);
}

/*********************************************************************************************************
** Function name:           drawRectangle
** Descriptions:            drawRectangle
*********************************************************************************************************/
void ePaper::drawRectangle(int poX, int poY, int len, int width)
{
    drawHorizontalLine(poX, poY, len);
    drawHorizontalLine(poX, poY+width, len);
    drawVerticalLine(poX, poY, width);
    drawVerticalLine(poX + len, poY, width);
}

/*********************************************************************************************************
** Function name:           fillCircle
** Descriptions:            fillCircle
*********************************************************************************************************/
void ePaper::fillCircle(int poX, int poY, int r)
{
    int x = -r, y = 0, err = 2-2*r, e2;

    do {

        drawVerticalLine(poX-x, poY-y, 2*y);
        drawVerticalLine(poX+x, poY-y, 2*y);

        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);

}

/*********************************************************************************************************
** Function name:           drawTraingle
** Descriptions:            drawTraingle
*********************************************************************************************************/
void ePaper::drawTraingle( int poX1, int poY1, int poX2, int poY2, int poX3, int poY3)
{
    drawLine(poX1, poY1, poX2, poY2);
    drawLine(poX1, poY1, poX3, poY3);
    drawLine(poX2, poY2, poX3, poY3);
}

/*********************************************************************************************************
** Function name:           drawTraingle
** Descriptions:            drawTraingle
*********************************************************************************************************/
void ePaper::fillRectangle(int poX, int poY, int len, int width)
{
    for(int i=0; i<width; i++)
    {
        drawHorizontalLine(poX, poY+i, len);
    }
}

/*********************************************************************************************************
** Function name:           display
** Descriptions:            you should use this function once after finish drawing
*********************************************************************************************************/
unsigned char ePaper::display()
{
    start();
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega328P__)
    EPD.image_sd();
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    EPD.image_sram(eSD.sram_image);
#endif
    end();
}

ePaper EPAPER;
/*********************************************************************************************************
  END FILE
*********************************************************************************************************/
<commit_msg>Removed useless comments and dead code<commit_after>/*
  ePaper.cpp
  2013 Copyright (c) Seeed Technology Inc.  All right reserved.

  Modified by Loovee
  www.seeedstudio.com
  2013-7-2

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <Arduino.h>
#include <SPI.h>
#include "GT20L16_drive.h"
#include "ePaper.h"

static void spi_on(){
    SPI.begin();
}

void ePaper::begin(EPD_size sz){
    size = sz;
    direction = DIRNORMAL;

    DISP_LEN    = 200;
    DISP_WIDTH  = 96;

    EPD.begin(size);
    init_io();
}

void ePaper::start(){
    EPD.start();
}

void ePaper::end(){
    EPD.end();
}

void ePaper::init_io(){
    pinMode(Pin_BUSY, INPUT);
    pinMode(Pin_RESET, OUTPUT);
    pinMode(Pin_PANEL_ON, OUTPUT);
    pinMode(Pin_DISCHARGE, OUTPUT);
    pinMode(Pin_BORDER, OUTPUT);
    pinMode(Pin_EPD_CS, OUTPUT);
    pinMode(Pin_SD_CS, OUTPUT);

    pinMode(9, OUTPUT);
    digitalWrite(9, HIGH);

    digitalWrite(Pin_RESET, LOW);
    digitalWrite(Pin_PANEL_ON, LOW);
    digitalWrite(Pin_DISCHARGE, LOW);
    digitalWrite(Pin_BORDER, LOW);
    digitalWrite(Pin_EPD_CS, HIGH);
    digitalWrite(Pin_SD_CS, HIGH);

    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
}

int ePaper::drawUnicode(unsigned int uniCode, int x, int y) {

    int dtaLen = GT20L16.getMatrixUnicode(uniCode, tMatrix);

    int pX      = 0;
    int pY      = 0;
    int color   = 0;

    for(int k = 0; k<2; k++)
    {
        for(int i=0; i<8; i++)
        {
            for(int j=0; j<(dtaLen/2); j++)
            {

                if(tMatrix[j+(dtaLen/2)*k] & (0x01<<(7-i)))
                {
                    color = 1;
                }
                else
                {
                    color = 0;
                }

                pX = x + j;
                pY = y + k*8+i;

                drawPixel(pX, pY, color);
            }
        }
    }

    return dtaLen/2;        // x +
}

int ePaper::drawUnicode(unsigned char *matrix, int x, int y)
{

    int dtaLen  = 32;
    int pX      = 0;
    int pY      = 0;
    int color   = 0;
    //spi_on();
    for(int k = 0; k<2; k++)
    {
        for(int i=0; i<8; i++)
        {
            for(int j=0; j<(dtaLen/2); j++)
            {

                if(matrix[j+(dtaLen/2)*k] & (0x01<<(7-i)))
                {
                    color = 1;
                }
                else
                {
                    color = 0;
                }

                pX = x + j;
                pY = y + k*8+i;

                drawPixel(pX, pY, color);
            }
        }
    }

    return dtaLen/2;        // x +
}

int ePaper::drawUnicodeString(unsigned int *uniCode, int len, int x, int y)
{
    int xPlus = 0;
    int xSum  = 0;

    for(int i=0; i<len; i++)
    {
        xPlus = drawUnicode(uniCode[i], x, y);
        x += xPlus;
        xSum += xPlus;
    }
    return xSum;
}

int ePaper::drawChar(char c, int x, int y)
{
    return drawUnicode(c, x, y);
}

int ePaper::drawString(char *string, int poX, int poY)
{
    int sumX = 0;

    while(*string)
    {

        int xPlus = drawChar(*string, poX, poY);
        sumX += xPlus;
        *string++;

        if(poX < 200)
        {
            poX += xPlus;                                     /* Move cursor right            */
        }
    }

    return sumX;
}

int ePaper::drawNumber(long long_num,int poX, int poY)
{
    char tmp[10];
    sprintf(tmp, "%d", long_num);
    return drawString(tmp, poX, poY);

}

int ePaper::drawFloat(float floatNumber, int decimal, int poX, int poY)
{
    unsigned long temp=0;
    float decy=0.0;
    float rounding = 0.5;
    unsigned char f=0;

    float eep = 0.000001;

    int sumX    = 0;
    int xPlus   = 0;

    if(floatNumber-0.0 < eep)       // floatNumber < 0
    {
        xPlus = drawChar('-',poX, poY);
        floatNumber = -floatNumber;

        poX  += xPlus;
        sumX += xPlus;
    }

    for (unsigned char i=0; i<decimal; ++i)
    {
        rounding /= 10.0;
    }

    floatNumber += rounding;

    temp = (long)floatNumber;

    xPlus = drawNumber(temp,poX, poY);

    poX  += xPlus;
    sumX += xPlus;

    if(decimal>0)
    {
        xPlus = drawChar('.',poX, poY);
        poX += xPlus;                                       /* Move cursor right            */
        sumX += xPlus;
    }
    else
    {
        return sumX;
    }

    decy = floatNumber - temp;
    for(unsigned char i=0; i<decimal; i++)
    {
        decy *= 10;                                                      /* for the next decimal         */
        temp = decy;                                                    /* get the decimal              */
        xPlus = drawNumber(temp,poX, poY);

        poX += xPlus;                                       /* Move cursor right            */
        sumX += xPlus;
        decy -= temp;
    }
    return sumX;
}

void ePaper::drawLine(int x0, int y0, int x1, int y1)
{

    init_io();

    int x = x1-x0;
    int y = y1-y0;
    int dx = abs(x), sx = x0<x1 ? 1 : -1;
    int dy = -abs(y), sy = y0<y1 ? 1 : -1;
    int err = dx+dy, e2;
    for (;;)
    {
        drawPixel(x0,y0,1);
        e2 = 2*err;
        if (e2 >= dy)
        {
            if (x0 == x1) break;
            err += dy; x0 += sx;
        }
        if (e2 <= dx)
        {
            if (y0 == y1) break;
            err += dx; y0 += sy;
        }
    }
}

void ePaper::clear_sd()
{

    init_io();

    for(int i=0; i<DISP_WIDTH; i++)
    {
        for(int j=0; j<DISP_LEN; j++)
        {
            drawPixel(j, i, 0);

        }
    }
}

void ePaper::drawCircle(int poX, int poY, int r)
{

    init_io();
    int x = -r, y = 0, err = 2-2*r, e2;
    do {
        drawPixel(poX-x, poY+y, 1);
        drawPixel(poX+x, poY+y, 1);
        drawPixel(poX+x, poY-y, 1);
        drawPixel(poX-x, poY-y, 1);
        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);
}

void ePaper::drawHorizontalLine( int poX, int poY, int len)
{
    drawLine(poX, poY, poX+len, poY);
}

void ePaper::drawVerticalLine( int poX, int poY, int len)
{
    drawLine(poX, poY, poX, poY+len);
}

void ePaper::drawRectangle(int poX, int poY, int len, int width)
{
    drawHorizontalLine(poX, poY, len);
    drawHorizontalLine(poX, poY+width, len);
    drawVerticalLine(poX, poY, width);
    drawVerticalLine(poX + len, poY, width);
}

void ePaper::fillCircle(int poX, int poY, int r)
{
    int x = -r, y = 0, err = 2-2*r, e2;

    do {

        drawVerticalLine(poX-x, poY-y, 2*y);
        drawVerticalLine(poX+x, poY-y, 2*y);

        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);

}

void ePaper::drawTraingle( int poX1, int poY1, int poX2, int poY2, int poX3, int poY3)
{
    drawLine(poX1, poY1, poX2, poY2);
    drawLine(poX1, poY1, poX3, poY3);
    drawLine(poX2, poY2, poX3, poY3);
}

void ePaper::fillRectangle(int poX, int poY, int len, int width)
{
    for(int i=0; i<width; i++)
    {
        drawHorizontalLine(poX, poY+i, len);
    }
}

unsigned char ePaper::display()
{
    start();
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega328P__)
    EPD.image_sd();
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    EPD.image_sram(eSD.sram_image);
#endif
    end();
}

ePaper EPAPER;
<|endoftext|>


<commit_before><commit_msg>Oilpan: ASan build fix after r198184<commit_after><|endoftext|>


<commit_before><commit_msg>computeCI(): Constify read-only variable<commit_after><|endoftext|>


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

#include "lld/Driver/WinLinkInputGraph.h"

namespace lld {

/// \brief Parse the input file to lld::File.
error_code PECOFFFileNode::parse(const LinkingContext &ctx,
                                 raw_ostream &diagnostics) {
  ErrorOr<StringRef> filePath = getPath(ctx);
  if (!filePath) {
    diagnostics << "File not found: " << _path << "\n";
    return error_code(filePath);
  }

  if (error_code ec = getBuffer(*filePath)) {
    diagnostics << "Cannot open file: " << *filePath << "\n";
    return ec;
  }

  if (ctx.logInputFiles())
    diagnostics << *filePath << "\n";

  if (filePath->endswith(".objtxt"))
    return ctx.getYAMLReader().parseFile(_buffer, _files);

  llvm::sys::fs::file_magic FileType =
      llvm::sys::fs::identify_magic(_buffer->getBuffer());
  std::unique_ptr<File> f;

  switch (FileType) {
  case llvm::sys::fs::file_magic::archive: {
    // Archive File
    error_code ec;
    f.reset(new FileArchive(ctx, std::move(_buffer), ec, false));
    _files.push_back(std::move(f));
    return ec;
  }
  case llvm::sys::fs::file_magic::coff_object:
  default:
    return _ctx.getDefaultReader().parseFile(_buffer, _files);
  }
}

ErrorOr<File &> PECOFFFileNode::getNextFile() {
  if (_nextFileIndex == _files.size())
    return make_error_code(InputGraphError::no_more_files);
  return *_files[_nextFileIndex++];
}

ErrorOr<StringRef> PECOFFFileNode::getPath(const LinkingContext &) const {
  if (_path.endswith_lower(".lib"))
    return _ctx.searchLibraryFile(_path);
  if (llvm::sys::path::extension(_path).empty())
    return _ctx.allocate(_path.str() + ".obj");
  return _path;
}

ErrorOr<StringRef> PECOFFLibraryNode::getPath(const LinkingContext &) const {
  if (_path.endswith_lower(".lib"))
    return _ctx.searchLibraryFile(_path);
  return _ctx.searchLibraryFile(_ctx.allocate(_path.str() + ".lib"));
}

} // end anonymous namespace
<commit_msg>Simplify a switch statement.<commit_after>//===- lib/Driver/WinLinkInputGraph.cpp -----------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lld/Driver/WinLinkInputGraph.h"

using llvm::sys::fs::file_magic;
using llvm::sys::fs::identify_magic;

namespace lld {

/// \brief Parse the input file to lld::File.
error_code PECOFFFileNode::parse(const LinkingContext &ctx,
                                 raw_ostream &diagnostics) {
  ErrorOr<StringRef> filePath = getPath(ctx);
  if (!filePath) {
    diagnostics << "File not found: " << _path << "\n";
    return error_code(filePath);
  }

  if (error_code ec = getBuffer(*filePath)) {
    diagnostics << "Cannot open file: " << *filePath << "\n";
    return ec;
  }

  if (ctx.logInputFiles())
    diagnostics << *filePath << "\n";

  if (filePath->endswith(".objtxt"))
    return ctx.getYAMLReader().parseFile(_buffer, _files);
  if (identify_magic(_buffer->getBuffer()) == file_magic::archive) {
    // Archive File
    error_code ec;
    _files.push_back(std::unique_ptr<File>(
                       new FileArchive(ctx, std::move(_buffer), ec, false)));
    return ec;
  }
  return _ctx.getDefaultReader().parseFile(_buffer, _files);
}

ErrorOr<File &> PECOFFFileNode::getNextFile() {
  if (_nextFileIndex == _files.size())
    return make_error_code(InputGraphError::no_more_files);
  return *_files[_nextFileIndex++];
}

ErrorOr<StringRef> PECOFFFileNode::getPath(const LinkingContext &) const {
  if (_path.endswith_lower(".lib"))
    return _ctx.searchLibraryFile(_path);
  if (llvm::sys::path::extension(_path).empty())
    return _ctx.allocate(_path.str() + ".obj");
  return _path;
}

ErrorOr<StringRef> PECOFFLibraryNode::getPath(const LinkingContext &) const {
  if (_path.endswith_lower(".lib"))
    return _ctx.searchLibraryFile(_path);
  return _ctx.searchLibraryFile(_ctx.allocate(_path.str() + ".lib"));
}

} // end anonymous namespace
<|endoftext|>


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

#include "clang/Frontend/FrontendActions.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/AnalysisConsumer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FixItRewriter.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// AST Consumer Actions
//===----------------------------------------------------------------------===//

ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
                                               llvm::StringRef InFile) {
  return CreateAnalysisConsumer(CI.getPreprocessor(),
                                CI.getFrontendOpts().OutputFile,
                                CI.getAnalyzerOpts());
}

ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
                                               llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
    return CreateASTPrinter(OS);
  return 0;
}

ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
                                                  llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
    return CreateASTPrinterXML(OS);
  return 0;
}

ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
                                              llvm::StringRef InFile) {
  return CreateASTDumper();
}

ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
                                              llvm::StringRef InFile) {
  return CreateASTViewer();
}

ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
                                                       llvm::StringRef InFile) {
  return CreateDeclContextPrinter();
}

ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI,
                                                 llvm::StringRef InFile) {
  return CreateRecordLayoutDumper();
}

ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
                                                  llvm::StringRef InFile) {
  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
  if (CI.getFrontendOpts().RelocatablePCH &&
      Sysroot.empty()) {
    CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
    return 0;
  }

  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
  if (!OS)
    return 0;

  if (CI.getFrontendOpts().RelocatablePCH)
    return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());

  return CreatePCHGenerator(CI.getPreprocessor(), OS);
}

ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
                                                llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
    return CreateHTMLPrinter(OS, CI.getPreprocessor());
  return 0;
}

ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
                                                      llvm::StringRef InFile) {
  return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
}

FixItAction::FixItAction() {}
FixItAction::~FixItAction() {}

ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
                                            llvm::StringRef InFile) {
  return new ASTConsumer();
}

/// AddFixItLocations - Add any individual user specified "fix-it" locations,
/// and return true on success.
static bool AddFixItLocations(CompilerInstance &CI,
                              FixItRewriter &FixItRewrite) {
  const std::vector<ParsedSourceLocation> &Locs =
    CI.getFrontendOpts().FixItLocations;
  for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
    const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
    if (!File) {
      CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
        << Locs[i].FileName;
      return false;
    }

    RequestedSourceLocation Requested;
    Requested.File = File;
    Requested.Line = Locs[i].Line;
    Requested.Column = Locs[i].Column;
    FixItRewrite.addFixItLocation(Requested);
  }

  return true;
}

bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
                                        llvm::StringRef Filename) {
  Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
                                   CI.getLangOpts()));
  if (!AddFixItLocations(CI, *Rewriter))
    return false;

  return true;
}

void FixItAction::EndSourceFileAction() {
  const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
  Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile);
}

ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
                                                  llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
    return CreateObjCRewriter(InFile, OS,
                              CI.getDiagnostics(), CI.getLangOpts(),
                              CI.getDiagnosticOpts().NoRewriteMacros);
  return 0;
}

ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
                                                 llvm::StringRef InFile) {
  return new ASTConsumer();
}

CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {}

ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
                                              llvm::StringRef InFile) {
  BackendAction BA = static_cast<BackendAction>(Act);
  llvm::OwningPtr<llvm::raw_ostream> OS;
  switch (BA) {
  case Backend_EmitAssembly:
    OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
    break;
  case Backend_EmitLL:
    OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
    break;
  case Backend_EmitBC:
    OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
    break;
  case Backend_EmitNothing:
    break;
  }
  if (BA != Backend_EmitNothing && !OS)
    return 0;

  return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
                               CI.getCodeGenOpts(), CI.getTargetOpts(),
                               CI.getFrontendOpts().ShowTimers, InFile,
                               OS.take(), CI.getLLVMContext());
}

EmitAssemblyAction::EmitAssemblyAction()
  : CodeGenAction(Backend_EmitAssembly) {}

EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {}

EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {}

EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {}

//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//

void DumpRawTokensAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  SourceManager &SM = PP.getSourceManager();

  // Start lexing the specified input file.
  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
  RawLex.SetKeepWhitespaceMode(true);

  Token RawTok;
  RawLex.LexFromRawLexer(RawTok);
  while (RawTok.isNot(tok::eof)) {
    PP.DumpToken(RawTok, true);
    llvm::errs() << "\n";
    RawLex.LexFromRawLexer(RawTok);
  }
}

void DumpTokensAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  // Start preprocessing the specified input file.
  Token Tok;
  PP.EnterMainSourceFile();
  do {
    PP.Lex(Tok);
    PP.DumpToken(Tok, true);
    llvm::errs() << "\n";
  } while (Tok.isNot(tok::eof));
}

void GeneratePTHAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  if (CI.getFrontendOpts().OutputFile.empty() ||
      CI.getFrontendOpts().OutputFile == "-") {
    // FIXME: Don't fail this way.
    // FIXME: Verify that we can actually seek in the given file.
    llvm::llvm_report_error("PTH requires a seekable file for output!");
  }
  llvm::raw_fd_ostream *OS =
    CI.createDefaultOutputFile(true, getCurrentFile());
  if (!OS) return;

  CacheTokens(CI.getPreprocessor(), OS);
}

void ParseOnlyAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  llvm::OwningPtr<Action> PA(new MinimalAction(PP));

  Parser P(PP, *PA);
  PP.EnterMainSourceFile();
  P.ParseTranslationUnit();
}

void PreprocessOnlyAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();

  Token Tok;
  // Start parsing the specified input file.
  PP.EnterMainSourceFile();
  do {
    PP.Lex(Tok);
  } while (Tok.isNot(tok::eof));
}

void PrintParseAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  if (!OS) return;

  llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));

  Parser P(PP, *PA);
  PP.EnterMainSourceFile();
  P.ParseTranslationUnit();
}

void PrintPreprocessedAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  if (!OS) return;

  DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
                           CI.getPreprocessorOutputOpts());
}

void RewriteMacrosAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  if (!OS) return;

  RewriteMacrosInInput(CI.getPreprocessor(), OS);
}

void RewriteTestAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  if (!OS) return;

  DoRewriteTest(CI.getPreprocessor(), OS);
}
<commit_msg>Fix <rdar://problem/7490212> clang rewriter: return of the mixed line endings, which is related to <rdar://problem/6596843> clang ObjC rewriter: Line endings still mixed in rewrite output<commit_after>//===--- FrontendActions.cpp ----------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/FrontendActions.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Parser.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/AnalysisConsumer.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FixItRewriter.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// AST Consumer Actions
//===----------------------------------------------------------------------===//

ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI,
                                               llvm::StringRef InFile) {
  return CreateAnalysisConsumer(CI.getPreprocessor(),
                                CI.getFrontendOpts().OutputFile,
                                CI.getAnalyzerOpts());
}

ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
                                               llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
    return CreateASTPrinter(OS);
  return 0;
}

ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
                                                  llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
    return CreateASTPrinterXML(OS);
  return 0;
}

ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
                                              llvm::StringRef InFile) {
  return CreateASTDumper();
}

ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
                                              llvm::StringRef InFile) {
  return CreateASTViewer();
}

ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
                                                       llvm::StringRef InFile) {
  return CreateDeclContextPrinter();
}

ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI,
                                                 llvm::StringRef InFile) {
  return CreateRecordLayoutDumper();
}

ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
                                                  llvm::StringRef InFile) {
  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
  if (CI.getFrontendOpts().RelocatablePCH &&
      Sysroot.empty()) {
    CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
    return 0;
  }

  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
  if (!OS)
    return 0;

  if (CI.getFrontendOpts().RelocatablePCH)
    return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str());

  return CreatePCHGenerator(CI.getPreprocessor(), OS);
}

ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
                                                llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
    return CreateHTMLPrinter(OS, CI.getPreprocessor());
  return 0;
}

ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
                                                      llvm::StringRef InFile) {
  return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
}

FixItAction::FixItAction() {}
FixItAction::~FixItAction() {}

ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
                                            llvm::StringRef InFile) {
  return new ASTConsumer();
}

/// AddFixItLocations - Add any individual user specified "fix-it" locations,
/// and return true on success.
static bool AddFixItLocations(CompilerInstance &CI,
                              FixItRewriter &FixItRewrite) {
  const std::vector<ParsedSourceLocation> &Locs =
    CI.getFrontendOpts().FixItLocations;
  for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
    const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
    if (!File) {
      CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
        << Locs[i].FileName;
      return false;
    }

    RequestedSourceLocation Requested;
    Requested.File = File;
    Requested.Line = Locs[i].Line;
    Requested.Column = Locs[i].Column;
    FixItRewrite.addFixItLocation(Requested);
  }

  return true;
}

bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
                                        llvm::StringRef Filename) {
  Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
                                   CI.getLangOpts()));
  if (!AddFixItLocations(CI, *Rewriter))
    return false;

  return true;
}

void FixItAction::EndSourceFileAction() {
  const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
  Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile);
}

ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
                                                  llvm::StringRef InFile) {
  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
    return CreateObjCRewriter(InFile, OS,
                              CI.getDiagnostics(), CI.getLangOpts(),
                              CI.getDiagnosticOpts().NoRewriteMacros);
  return 0;
}

ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
                                                 llvm::StringRef InFile) {
  return new ASTConsumer();
}

CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {}

ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI,
                                              llvm::StringRef InFile) {
  BackendAction BA = static_cast<BackendAction>(Act);
  llvm::OwningPtr<llvm::raw_ostream> OS;
  switch (BA) {
  case Backend_EmitAssembly:
    OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
    break;
  case Backend_EmitLL:
    OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
    break;
  case Backend_EmitBC:
    OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
    break;
  case Backend_EmitNothing:
    break;
  }
  if (BA != Backend_EmitNothing && !OS)
    return 0;

  return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(),
                               CI.getCodeGenOpts(), CI.getTargetOpts(),
                               CI.getFrontendOpts().ShowTimers, InFile,
                               OS.take(), CI.getLLVMContext());
}

EmitAssemblyAction::EmitAssemblyAction()
  : CodeGenAction(Backend_EmitAssembly) {}

EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {}

EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {}

EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {}

//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//

void DumpRawTokensAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  SourceManager &SM = PP.getSourceManager();

  // Start lexing the specified input file.
  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
  RawLex.SetKeepWhitespaceMode(true);

  Token RawTok;
  RawLex.LexFromRawLexer(RawTok);
  while (RawTok.isNot(tok::eof)) {
    PP.DumpToken(RawTok, true);
    llvm::errs() << "\n";
    RawLex.LexFromRawLexer(RawTok);
  }
}

void DumpTokensAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  // Start preprocessing the specified input file.
  Token Tok;
  PP.EnterMainSourceFile();
  do {
    PP.Lex(Tok);
    PP.DumpToken(Tok, true);
    llvm::errs() << "\n";
  } while (Tok.isNot(tok::eof));
}

void GeneratePTHAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  if (CI.getFrontendOpts().OutputFile.empty() ||
      CI.getFrontendOpts().OutputFile == "-") {
    // FIXME: Don't fail this way.
    // FIXME: Verify that we can actually seek in the given file.
    llvm::llvm_report_error("PTH requires a seekable file for output!");
  }
  llvm::raw_fd_ostream *OS =
    CI.createDefaultOutputFile(true, getCurrentFile());
  if (!OS) return;

  CacheTokens(CI.getPreprocessor(), OS);
}

void ParseOnlyAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  llvm::OwningPtr<Action> PA(new MinimalAction(PP));

  Parser P(PP, *PA);
  PP.EnterMainSourceFile();
  P.ParseTranslationUnit();
}

void PreprocessOnlyAction::ExecuteAction() {
  Preprocessor &PP = getCompilerInstance().getPreprocessor();

  Token Tok;
  // Start parsing the specified input file.
  PP.EnterMainSourceFile();
  do {
    PP.Lex(Tok);
  } while (Tok.isNot(tok::eof));
}

void PrintParseAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  Preprocessor &PP = getCompilerInstance().getPreprocessor();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  if (!OS) return;

  llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));

  Parser P(PP, *PA);
  PP.EnterMainSourceFile();
  P.ParseTranslationUnit();
}

void PrintPreprocessedAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  // Output file needs to be set to 'Binary', to avoid converting Unix style
  // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  if (!OS) return;

  DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
                           CI.getPreprocessorOutputOpts());
}

void RewriteMacrosAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  if (!OS) return;

  RewriteMacrosInInput(CI.getPreprocessor(), OS);
}

void RewriteTestAction::ExecuteAction() {
  CompilerInstance &CI = getCompilerInstance();
  llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  if (!OS) return;

  DoRewriteTest(CI.getPreprocessor(), OS);
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

#include <string>

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  cling::ValuePrinterInfo VPI(Exp, Context);
  cling::printValuePublic(llvm::outs(), value, value, VPI);

  cling::flushOStream(llvm::outs());
}

static void StreamChar(llvm::raw_ostream& o, const char v,
                       const char* Sep = "\n") {
  o << '"' << v << "\"" << Sep;
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v,
                          const char* Sep = "\n") {
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"..." << Sep;
  else o << "\"" << Sep;
}

static void StreamRef(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o <<"&" << v << Sep;
}

static void StreamPtr(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o << v << Sep;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const cling::ValuePrinterInfo& VPI,
                        clang::QualType Ty,
                        const char* Sep = "\n");

static void StreamArr(llvm::raw_ostream& o, const void* p,
                      const cling::ValuePrinterInfo& VPI,
                      clang::QualType Ty,
                      const char* Sep = "\n") {
  const clang::ASTContext& C = *VPI.getASTContext();
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)p);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, ((char*)p) + i * ElBytes, VPI, ElementTy, " ");
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }" << Sep;
  } else
    StreamPtr(o, p, Sep);
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const cling::ValuePrinterInfo& VPI,
                      clang::QualType QTy,
                      const char* Sep = "\n") {
  const clang::Type* Ty = QTy.getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    const cling::Value* value = 0;
    if (CXXRD->getQualifiedNameAsString().compare("cling::StoredValueRef") == 0){
      const cling::StoredValueRef* VR = (const cling::StoredValueRef*)v;
      if (VR->isValid()) {
        value = &VR->get();
      } else {
        o << "<<<invalid>>> ";
      }
    } else if (CXXRD->getQualifiedNameAsString().compare("cling::Value") == 0) {
      value = (const cling::Value*)v;
    }
    if (value) {
      if (value->isValid()) {
        o << "boxes [";
        const clang::ASTContext& C = *VPI.getASTContext();
        o <<
          "(" <<
          value->type.getAsString(C.getPrintingPolicy()) <<
          ") ";
        clang::QualType valType = value->type.getDesugaredType(C);
        if (valType->isFloatingType())
          o << value->value.DoubleVal;
        else if (valType->isIntegerType())
          o << value->value.IntVal.getSExtValue();
        else if (valType->isBooleanType())
          o << value->value.IntVal.getBoolValue();
        else
          StreamValue(o, value->value.PointerVal, VPI, valType, "");
        o << "]" << Sep;

        return;
      } else
        o << "<<<invalid>>> ";
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << v << Sep;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const cling::ValuePrinterInfo& VPI,
                        clang::QualType Ty,
                        const char* Sep /*= "\n"*/) {
  const clang::ASTContext& C = *VPI.getASTContext();
  Ty = Ty.getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true" << Sep;
      else o << "false" << Sep; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p << Sep; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p << Sep;
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p << Sep; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p << Sep;
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p << Sep; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p << Sep;
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p << Sep;
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p << Sep;
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p << Sep; break;
    case clang::BuiltinType::Double: o << *(const double*)p << Sep; break;
    default:
      StreamObj(o, p, VPI, Ty, Sep);
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
    StreamObj(o, p, VPI, Ty, Sep);
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep);
  }
  else if (Ty->isEnumeralType()) {
    StreamObj(o, p, VPI, Ty, Sep);
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10) << Sep;
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p, Sep);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p, Sep);
    else
      StreamPtr(o, p, Sep);
  }
  else if (Ty->isArrayType())
    StreamArr(o, p, VPI, Ty, Sep);
  else
    StreamObj(o, p, VPI, Ty, Sep);
}

namespace cling {
  void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
                               const ValuePrinterInfo& VPI) {
    const clang::Expr* E = VPI.getExpr();
    o << "(";
    o << E->getType().getAsString();
    o << ") ";
    StreamValue(o, p, VPI, VPI.getExpr()->getType());
  }

  void flushOStream(llvm::raw_ostream& o) {
    o.flush();
  }

} // end namespace cling
<commit_msg>Const correctness.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"

#include <string>

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  cling::ValuePrinterInfo VPI(Exp, Context);
  cling::printValuePublic(llvm::outs(), value, value, VPI);

  cling::flushOStream(llvm::outs());
}

static void StreamChar(llvm::raw_ostream& o, const char v,
                       const char* Sep = "\n") {
  o << '"' << v << "\"" << Sep;
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v,
                          const char* Sep = "\n") {
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"..." << Sep;
  else o << "\"" << Sep;
}

static void StreamRef(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o <<"&" << v << Sep;
}

static void StreamPtr(llvm::raw_ostream& o, const void* v,
                      const char* Sep = "\n") {
  o << v << Sep;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const cling::ValuePrinterInfo& VPI,
                        clang::QualType Ty,
                        const char* Sep = "\n");

static void StreamArr(llvm::raw_ostream& o, const void* p,
                      const cling::ValuePrinterInfo& VPI,
                      clang::QualType Ty,
                      const char* Sep = "\n") {
  const clang::ASTContext& C = *VPI.getASTContext();
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)p);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, ((const char*)p) + i * ElBytes, VPI, ElementTy, " ");
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }" << Sep;
  } else
    StreamPtr(o, p, Sep);
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const cling::ValuePrinterInfo& VPI,
                      clang::QualType QTy,
                      const char* Sep = "\n") {
  const clang::Type* Ty = QTy.getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    const cling::Value* value = 0;
    if (CXXRD->getQualifiedNameAsString().compare("cling::StoredValueRef") == 0){
      const cling::StoredValueRef* VR = (const cling::StoredValueRef*)v;
      if (VR->isValid()) {
        value = &VR->get();
      } else {
        o << "<<<invalid>>> ";
      }
    } else if (CXXRD->getQualifiedNameAsString().compare("cling::Value") == 0) {
      value = (const cling::Value*)v;
    }
    if (value) {
      if (value->isValid()) {
        o << "boxes [";
        const clang::ASTContext& C = *VPI.getASTContext();
        o <<
          "(" <<
          value->type.getAsString(C.getPrintingPolicy()) <<
          ") ";
        clang::QualType valType = value->type.getDesugaredType(C);
        if (valType->isFloatingType())
          o << value->value.DoubleVal;
        else if (valType->isIntegerType())
          o << value->value.IntVal.getSExtValue();
        else if (valType->isBooleanType())
          o << value->value.IntVal.getBoolValue();
        else
          StreamValue(o, value->value.PointerVal, VPI, valType, "");
        o << "]" << Sep;

        return;
      } else
        o << "<<<invalid>>> ";
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << v << Sep;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const cling::ValuePrinterInfo& VPI,
                        clang::QualType Ty,
                        const char* Sep /*= "\n"*/) {
  const clang::ASTContext& C = *VPI.getASTContext();
  Ty = Ty.getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true" << Sep;
      else o << "false" << Sep; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p << Sep; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p << Sep;
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p << Sep; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p << Sep;
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p << Sep; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p << Sep;
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p << Sep;
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p << Sep;
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p << Sep; break;
    case clang::BuiltinType::Double: o << *(const double*)p << Sep; break;
    default:
      StreamObj(o, p, VPI, Ty, Sep);
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0) {
    StreamObj(o, p, VPI, Ty, Sep);
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()), Sep);
  }
  else if (Ty->isEnumeralType()) {
    StreamObj(o, p, VPI, Ty, Sep);
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10) << Sep;
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p, Sep);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p, Sep);
    else
      StreamPtr(o, p, Sep);
  }
  else if (Ty->isArrayType())
    StreamArr(o, p, VPI, Ty, Sep);
  else
    StreamObj(o, p, VPI, Ty, Sep);
}

namespace cling {
  void printValuePublicDefault(llvm::raw_ostream& o, const void* const p,
                               const ValuePrinterInfo& VPI) {
    const clang::Expr* E = VPI.getExpr();
    o << "(";
    o << E->getType().getAsString();
    o << ") ";
    StreamValue(o, p, VPI, VPI.getExpr()->getType());
  }

  void flushOStream(llvm::raw_ostream& o) {
    o.flush();
  }

} // end namespace cling
<|endoftext|>


<commit_before>
#include "BasicBlock.h"

#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

const char* BasicBlock::NamePrefix = "Instr.";

BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) :
	m_beginInstIdx(_beginInstIdx),
	m_endInstIdx(_endInstIdx),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)),
	m_stack(m_llvmBB)
{}

BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) :
	m_beginInstIdx(0),
	m_endInstIdx(0),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
	m_stack(m_llvmBB)
{}

void BasicBlock::Stack::push(llvm::Value* _value)
{
	m_backend.push_back(_value);
}

llvm::Value* BasicBlock::Stack::pop()
{
	auto top = get(0);
	m_backend.pop_back();
	return top;
}

llvm::Value* BasicBlock::Stack::get(size_t _index)
{
	if (_index >= m_backend.size())
	{
		// Create PHI node for missing values
		auto nMissingVals = _index - m_backend.size() + 1;
		m_backend.insert(m_backend.begin(), nMissingVals, nullptr);
		for (decltype(nMissingVals) i = 0; i < nMissingVals; ++i)
		{
			m_backend[i] = m_llvmBB->empty() ?
				llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) :
				llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI());
		}
	}

	return *(m_backend.rbegin() + _index);
}

void BasicBlock::Stack::dup(size_t _index)
{
	m_backend.push_back(get(_index));
}

void BasicBlock::Stack::swap(size_t _index)
{
	assert(_index != 0);
	get(_index); // Create PHI nodes
	std::swap(*m_backend.rbegin(), *(m_backend.rbegin() + _index));
}

}
}
}

<commit_msg>Check if pushed item is a word<commit_after>
#include "BasicBlock.h"

#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

const char* BasicBlock::NamePrefix = "Instr.";

BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) :
	m_beginInstIdx(_beginInstIdx),
	m_endInstIdx(_endInstIdx),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)),
	m_stack(m_llvmBB)
{}

BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) :
	m_beginInstIdx(0),
	m_endInstIdx(0),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
	m_stack(m_llvmBB)
{}

void BasicBlock::Stack::push(llvm::Value* _value)
{
	assert(_value->getType() == Type::i256);
	m_backend.push_back(_value);
}

llvm::Value* BasicBlock::Stack::pop()
{
	auto top = get(0);
	m_backend.pop_back();
	return top;
}

llvm::Value* BasicBlock::Stack::get(size_t _index)
{
	if (_index >= m_backend.size())
	{
		// Create PHI node for missing values
		auto nMissingVals = _index - m_backend.size() + 1;
		m_backend.insert(m_backend.begin(), nMissingVals, nullptr);
		for (decltype(nMissingVals) i = 0; i < nMissingVals; ++i)
		{
			m_backend[i] = m_llvmBB->empty() ?
				llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB) :
				llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI());
		}
	}

	return *(m_backend.rbegin() + _index);
}

void BasicBlock::Stack::dup(size_t _index)
{
	m_backend.push_back(get(_index));
}

void BasicBlock::Stack::swap(size_t _index)
{
	assert(_index != 0);
	get(_index); // Create PHI nodes
	std::swap(*m_backend.rbegin(), *(m_backend.rbegin() + _index));
}

}
}
}

<|endoftext|>


<commit_before>
#include "BasicBlock.h"

#include <iostream>

#include <llvm/IR/CFG.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

const char* BasicBlock::NamePrefix = "Instr.";

BasicBlock::BasicBlock(bytes::const_iterator _begin, bytes::const_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) :
	m_begin(_begin),
	m_end(_end),
	// TODO: Add begin index to name
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), NamePrefix, _mainFunc)),
	m_stack(*this),
	m_builder(_builder),
	m_isJumpDest(isJumpDest)
{}

BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) :
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
	m_stack(*this),
	m_builder(_builder),
	m_isJumpDest(isJumpDest)
{}

BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) :
	m_bblock(_owner)
{}

void BasicBlock::LocalStack::push(llvm::Value* _value)
{
	m_bblock.m_currentStack.push_back(_value);
	m_bblock.m_tosOffset += 1;
}

llvm::Value* BasicBlock::LocalStack::pop()
{
	auto result = get(0);

	if (m_bblock.m_currentStack.size() > 0)
		m_bblock.m_currentStack.pop_back();

	m_bblock.m_tosOffset -= 1;
	return result;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void BasicBlock::LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void BasicBlock::LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index)
{
	auto& currentStack = m_bblock.m_currentStack;
	if (_index < currentStack.size())
		return currentStack.end() - _index - 1;

	// Need to map more elements from the EVM stack
	auto nNewItems = 1 + _index - currentStack.size();
	currentStack.insert(currentStack.begin(), nNewItems, nullptr);

	return currentStack.end() - _index - 1;
}

llvm::Value* BasicBlock::LocalStack::get(size_t _index)
{
	auto& initialStack = m_bblock.m_initialStack;
	auto itemIter = getItemIterator(_index);

	if (*itemIter == nullptr)
	{
		// Need to fetch a new item from the EVM stack
		assert(static_cast<int>(_index) >= m_bblock.m_tosOffset);
		size_t initialIdx = _index - m_bblock.m_tosOffset;
		if (initialIdx >= initialStack.size())
		{
			auto nNewItems = 1 + initialIdx - initialStack.size();
			initialStack.insert(initialStack.end(), nNewItems, nullptr);
		}

		assert(initialStack[initialIdx] == nullptr);
		// Create a dummy value.
		std::string name = "get_" + std::to_string(_index);
		initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, std::move(name));
		*itemIter = initialStack[initialIdx];
	}

	return *itemIter;
}

void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
{
	auto itemIter = getItemIterator(_index);
	*itemIter = _word;
}

void BasicBlock::synchronizeLocalStack(Stack& _evmStack)
{
	auto blockTerminator = m_llvmBB->getTerminator();
	assert(blockTerminator != nullptr);
	m_builder.SetInsertPoint(blockTerminator);

	auto currIter = m_currentStack.begin();
	auto endIter = m_currentStack.end();

	// Update (emit set()) changed values
	for (int idx = m_currentStack.size() - 1 - m_tosOffset;
		 currIter < endIter && idx >= 0;
		 ++currIter, --idx)
	{
		assert(static_cast<size_t>(idx) < m_initialStack.size());
		if (*currIter != m_initialStack[idx]) // value needs update
			_evmStack.set(static_cast<size_t>(idx), *currIter);
	}

	if (m_tosOffset < 0)
	{
		// Pop values
		_evmStack.pop(static_cast<size_t>(-m_tosOffset));
	}

	// Push new values
	for (; currIter < endIter; ++currIter)
	{
		assert(*currIter != nullptr);
		_evmStack.push(*currIter);
	}

	// Emit get() for all (used) values from the initial stack
	for (size_t idx = 0; idx < m_initialStack.size(); ++idx)
	{
		auto val = m_initialStack[idx];
		if (val == nullptr)
			continue;

		assert(llvm::isa<llvm::PHINode>(val));
		llvm::PHINode* phi = llvm::cast<llvm::PHINode>(val);
		if (! phi->use_empty())
		{
			// Insert call to get() just before the PHI node and replace
			// the uses of PHI with the uses of this new instruction.
			m_builder.SetInsertPoint(phi);
			auto newVal = _evmStack.get(idx);
			phi->replaceAllUsesWith(newVal);
		}
		phi->eraseFromParent();
	}

	// Reset the stack
	m_initialStack.erase(m_initialStack.begin(), m_initialStack.end());
	m_currentStack.erase(m_currentStack.begin(), m_currentStack.end());
	m_tosOffset = 0;
}

void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
	struct BBInfo
	{
		BasicBlock& bblock;
		std::vector<BBInfo*> predecessors;
		size_t inputItems;
		size_t outputItems;
		std::vector<llvm::PHINode*> phisToRewrite;

		BBInfo(BasicBlock& _bblock) :
			bblock(_bblock),
			predecessors(),
			inputItems(0),
			outputItems(0)
		{
			auto& initialStack = bblock.m_initialStack;
			for (auto it = initialStack.begin();
				 it != initialStack.end() && *it != nullptr;
				 ++it, ++inputItems);

			//if (bblock.localStack().m_tosOffset > 0)
			//	outputItems = bblock.localStack().m_tosOffset;
			auto& exitStack = bblock.m_currentStack;
			for (auto it = exitStack.rbegin();
				 it != exitStack.rend() && *it != nullptr;
				 ++it, ++outputItems);
		}
	};

	std::map<llvm::BasicBlock*, BBInfo> cfg;

	// Create nodes in cfg
	for (auto bb : basicBlocks)
		cfg.emplace(bb->llvm(), *bb);

	// Create edges in cfg: for each bb info fill the list
	// of predecessor infos.
	for (auto& pair : cfg)
	{
		auto bb = pair.first;
		auto& info = pair.second;

		for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt)
		{
			auto predInfoEntry = cfg.find(*predIt);
			if (predInfoEntry != cfg.end())
				info.predecessors.push_back(&predInfoEntry->second);
		}
	}

	// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
	bool valuesChanged = true;
	while (valuesChanged)
	{
		if (getenv("EVMCC_DEBUG_BLOCKS"))
		{
			for (auto& pair : cfg)
				std::cerr << pair.second.bblock.llvm()->getName().str()
						  << ": in " << pair.second.inputItems
						  << ", out " << pair.second.outputItems
						  << "\n";
		}

		valuesChanged = false;
		for (auto& pair : cfg)
		{
			auto& info = pair.second;

			if (info.predecessors.empty())
				info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false

			for (auto predInfo : info.predecessors)
			{
				if (predInfo->outputItems < info.inputItems)
				{
					info.inputItems = predInfo->outputItems;
					valuesChanged = true;
				}
				else if (predInfo->outputItems > info.inputItems)
				{
					predInfo->outputItems = info.inputItems;
					valuesChanged = true;
				}
			}
		}
	}

	// Propagate values between blocks.
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
		auto phiIter = bblock.m_initialStack.begin();
		for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
		{
			assert(llvm::isa<llvm::PHINode>(*phiIter));
			auto phi = llvm::cast<llvm::PHINode>(*phiIter);

			for (auto predIt : info.predecessors)
			{
				auto& predExitStack = predIt->bblock.m_currentStack;
				auto value = *(predExitStack.end() - 1 - index);
				phi->addIncoming(value, predIt->bblock.llvm());
			}

			// Move phi to the front
			if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin())
			{
				phi->removeFromParent();
				_builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin());
				_builder.Insert(phi);
			}
		}

		// The items pulled directly from predecessors block must be removed
		// from the list of items that has to be popped from the initial stack.
		auto& initialStack = bblock.m_initialStack;
		initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
		// Initial stack shrinks, so the size difference grows:
		bblock.m_tosOffset += info.inputItems;
	}

	// We must account for the items that were pushed directly to successor
	// blocks and thus should not be on the list of items to be pushed onto
	// to EVM stack
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		auto& exitStack = bblock.m_currentStack;
		exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
		bblock.m_tosOffset -= info.outputItems;
	}
}

void BasicBlock::dump()
{
	dump(std::cerr, false);
}

void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
{
	llvm::raw_os_ostream out(_out);

	out << (_dotOutput ? "" : "Initial stack:\n");
	for (auto val : m_initialStack)
	{
		if (val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(val))
			out << *val;
		else
			out << "  " << *val;

		out << (_dotOutput ? "\\l" : "\n");
	}

	out << (_dotOutput ? "| " : "Instructions:\n");
	for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins)
		out << *ins << (_dotOutput ? "\\l" : "\n");

	if (! _dotOutput)
		out << "Current stack (offset = " << m_tosOffset << "):\n";
	else
		out << "|";

	for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val)
	{
		if (*val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(*val))
			out << **val;
		else
			out << "  " << **val;
		out << (_dotOutput ? "\\l" : "\n");
	}

	if (! _dotOutput)
		out << "  ...\n----------------------------------------\n";
}

}
}
}

<commit_msg>Allways generate stack_get() call to detect stack underflow cases<commit_after>
#include "BasicBlock.h"

#include <iostream>

#include <llvm/IR/CFG.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>

#include "Type.h"

namespace dev
{
namespace eth
{
namespace jit
{

const char* BasicBlock::NamePrefix = "Instr.";

BasicBlock::BasicBlock(bytes::const_iterator _begin, bytes::const_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) :
	m_begin(_begin),
	m_end(_end),
	// TODO: Add begin index to name
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), NamePrefix, _mainFunc)),
	m_stack(*this),
	m_builder(_builder),
	m_isJumpDest(isJumpDest)
{}

BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) :
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
	m_stack(*this),
	m_builder(_builder),
	m_isJumpDest(isJumpDest)
{}

BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) :
	m_bblock(_owner)
{}

void BasicBlock::LocalStack::push(llvm::Value* _value)
{
	m_bblock.m_currentStack.push_back(_value);
	m_bblock.m_tosOffset += 1;
}

llvm::Value* BasicBlock::LocalStack::pop()
{
	auto result = get(0);

	if (m_bblock.m_currentStack.size() > 0)
		m_bblock.m_currentStack.pop_back();

	m_bblock.m_tosOffset -= 1;
	return result;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void BasicBlock::LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void BasicBlock::LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

std::vector<llvm::Value*>::iterator BasicBlock::LocalStack::getItemIterator(size_t _index)
{
	auto& currentStack = m_bblock.m_currentStack;
	if (_index < currentStack.size())
		return currentStack.end() - _index - 1;

	// Need to map more elements from the EVM stack
	auto nNewItems = 1 + _index - currentStack.size();
	currentStack.insert(currentStack.begin(), nNewItems, nullptr);

	return currentStack.end() - _index - 1;
}

llvm::Value* BasicBlock::LocalStack::get(size_t _index)
{
	auto& initialStack = m_bblock.m_initialStack;
	auto itemIter = getItemIterator(_index);

	if (*itemIter == nullptr)
	{
		// Need to fetch a new item from the EVM stack
		assert(static_cast<int>(_index) >= m_bblock.m_tosOffset);
		size_t initialIdx = _index - m_bblock.m_tosOffset;
		if (initialIdx >= initialStack.size())
		{
			auto nNewItems = 1 + initialIdx - initialStack.size();
			initialStack.insert(initialStack.end(), nNewItems, nullptr);
		}

		assert(initialStack[initialIdx] == nullptr);
		// Create a dummy value.
		std::string name = "get_" + std::to_string(_index);
		initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, std::move(name));
		*itemIter = initialStack[initialIdx];
	}

	return *itemIter;
}

void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
{
	auto itemIter = getItemIterator(_index);
	*itemIter = _word;
}

void BasicBlock::synchronizeLocalStack(Stack& _evmStack)
{
	auto blockTerminator = m_llvmBB->getTerminator();
	assert(blockTerminator != nullptr);
	m_builder.SetInsertPoint(blockTerminator);

	auto currIter = m_currentStack.begin();
	auto endIter = m_currentStack.end();

	// Update (emit set()) changed values
	for (int idx = m_currentStack.size() - 1 - m_tosOffset;
		 currIter < endIter && idx >= 0;
		 ++currIter, --idx)
	{
		assert(static_cast<size_t>(idx) < m_initialStack.size());
		if (*currIter != m_initialStack[idx]) // value needs update
			_evmStack.set(static_cast<size_t>(idx), *currIter);
	}

	if (m_tosOffset < 0)
	{
		// Pop values
		_evmStack.pop(static_cast<size_t>(-m_tosOffset));
	}

	// Push new values
	for (; currIter < endIter; ++currIter)
	{
		assert(*currIter != nullptr);
		_evmStack.push(*currIter);
	}

	// Emit get() for all (used) values from the initial stack
	for (size_t idx = 0; idx < m_initialStack.size(); ++idx)
	{
		auto val = m_initialStack[idx];
		if (val == nullptr)
			continue;

		llvm::PHINode* phi = llvm::cast<llvm::PHINode>(val);
		// Insert call to get() just before the PHI node and replace
		// the uses of PHI with the uses of this new instruction.
		m_builder.SetInsertPoint(phi);
		auto newVal = _evmStack.get(idx); // OPT: Value may be never user but we need to check stack heigth
		                                  //      It is probably a good idea to keep heigth as a local variable accesible by LLVM directly
		phi->replaceAllUsesWith(newVal);
		phi->eraseFromParent();
	}

	// Reset the stack
	m_initialStack.erase(m_initialStack.begin(), m_initialStack.end());
	m_currentStack.erase(m_currentStack.begin(), m_currentStack.end());
	m_tosOffset = 0;
}

void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
{
	struct BBInfo
	{
		BasicBlock& bblock;
		std::vector<BBInfo*> predecessors;
		size_t inputItems;
		size_t outputItems;
		std::vector<llvm::PHINode*> phisToRewrite;

		BBInfo(BasicBlock& _bblock) :
			bblock(_bblock),
			predecessors(),
			inputItems(0),
			outputItems(0)
		{
			auto& initialStack = bblock.m_initialStack;
			for (auto it = initialStack.begin();
				 it != initialStack.end() && *it != nullptr;
				 ++it, ++inputItems);

			//if (bblock.localStack().m_tosOffset > 0)
			//	outputItems = bblock.localStack().m_tosOffset;
			auto& exitStack = bblock.m_currentStack;
			for (auto it = exitStack.rbegin();
				 it != exitStack.rend() && *it != nullptr;
				 ++it, ++outputItems);
		}
	};

	std::map<llvm::BasicBlock*, BBInfo> cfg;

	// Create nodes in cfg
	for (auto bb : basicBlocks)
		cfg.emplace(bb->llvm(), *bb);

	// Create edges in cfg: for each bb info fill the list
	// of predecessor infos.
	for (auto& pair : cfg)
	{
		auto bb = pair.first;
		auto& info = pair.second;

		for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt)
		{
			auto predInfoEntry = cfg.find(*predIt);
			if (predInfoEntry != cfg.end())
				info.predecessors.push_back(&predInfoEntry->second);
		}
	}

	// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
	bool valuesChanged = true;
	while (valuesChanged)
	{
		if (getenv("EVMCC_DEBUG_BLOCKS"))
		{
			for (auto& pair : cfg)
				std::cerr << pair.second.bblock.llvm()->getName().str()
						  << ": in " << pair.second.inputItems
						  << ", out " << pair.second.outputItems
						  << "\n";
		}

		valuesChanged = false;
		for (auto& pair : cfg)
		{
			auto& info = pair.second;

			if (info.predecessors.empty())
				info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false

			for (auto predInfo : info.predecessors)
			{
				if (predInfo->outputItems < info.inputItems)
				{
					info.inputItems = predInfo->outputItems;
					valuesChanged = true;
				}
				else if (predInfo->outputItems > info.inputItems)
				{
					predInfo->outputItems = info.inputItems;
					valuesChanged = true;
				}
			}
		}
	}

	// Propagate values between blocks.
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
		auto phiIter = bblock.m_initialStack.begin();
		for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
		{
			assert(llvm::isa<llvm::PHINode>(*phiIter));
			auto phi = llvm::cast<llvm::PHINode>(*phiIter);

			for (auto predIt : info.predecessors)
			{
				auto& predExitStack = predIt->bblock.m_currentStack;
				auto value = *(predExitStack.end() - 1 - index);
				phi->addIncoming(value, predIt->bblock.llvm());
			}

			// Move phi to the front
			if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin())
			{
				phi->removeFromParent();
				_builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin());
				_builder.Insert(phi);
			}
		}

		// The items pulled directly from predecessors block must be removed
		// from the list of items that has to be popped from the initial stack.
		auto& initialStack = bblock.m_initialStack;
		initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
		// Initial stack shrinks, so the size difference grows:
		bblock.m_tosOffset += info.inputItems;
	}

	// We must account for the items that were pushed directly to successor
	// blocks and thus should not be on the list of items to be pushed onto
	// to EVM stack
	for (auto& entry : cfg)
	{
		auto& info = entry.second;
		auto& bblock = info.bblock;

		auto& exitStack = bblock.m_currentStack;
		exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
		bblock.m_tosOffset -= info.outputItems;
	}
}

void BasicBlock::dump()
{
	dump(std::cerr, false);
}

void BasicBlock::dump(std::ostream& _out, bool _dotOutput)
{
	llvm::raw_os_ostream out(_out);

	out << (_dotOutput ? "" : "Initial stack:\n");
	for (auto val : m_initialStack)
	{
		if (val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(val))
			out << *val;
		else
			out << "  " << *val;

		out << (_dotOutput ? "\\l" : "\n");
	}

	out << (_dotOutput ? "| " : "Instructions:\n");
	for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins)
		out << *ins << (_dotOutput ? "\\l" : "\n");

	if (! _dotOutput)
		out << "Current stack (offset = " << m_tosOffset << "):\n";
	else
		out << "|";

	for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val)
	{
		if (*val == nullptr)
			out << "  ?";
		else if (llvm::isa<llvm::Instruction>(*val))
			out << **val;
		else
			out << "  " << **val;
		out << (_dotOutput ? "\\l" : "\n");
	}

	if (! _dotOutput)
		out << "  ...\n----------------------------------------\n";
}

}
}
}

<|endoftext|>


<commit_before>/*
 * endian.hpp
 * Some functions for handling endian.
 *
 * written by janus_wel<janus.wel.3@gmail.com>
 * This source code is NOT MY COPYRIGHTED WORK, and has NO WARRANTY.
 *
 * Refer - a source of an idea:
 *  http://www.kijineko.co.jp/tech/cpptempls/endian
 * */

#ifndef ENDIAN_H
#define ENDIAN_H

#include <algorithm>
#include "cast.hpp"

namespace util {
    namespace endian {
        inline bool is_le() {
            // in a 32-bit machine, the representation of 1 is:
            //
            //      little endian: 01 00 00 00
            //      big endian:    00 00 00 01
            //
            // therefore the machine is little endian
            // if the first byte is 1 (actually 01).
            int t = 1;
            return *(util::cast::pointer_cast<char*>(&t)) == 1;
        }
        inline bool is_be() { return !is_le(); }

        // this is destructive but fast
        template<typename T> void fast_reverse(T& value) {
            char volatile* first = util::cast::pointer_cast<char volatile*>(&value);
            char volatile* last = first + sizeof(T);
            std::reverse(first, last);
        }

        // this is slow but nondestructive
        template<typename T> T reverse(const T& value) {
            T temp = value;
            char volatile* first = util::cast::pointer_cast<char volatile*>(&temp);
            char volatile* last = first + sizeof(T);
            std::reverse(first, last);
            return temp;
        }
    }
}

#endif // ENDIAN_H

<commit_msg>Change the names of functions and refactoring<commit_after>/*
 * endian.hpp
 * Some functions for handling endian.
 *
 * written by janus_wel<janus.wel.3@gmail.com>
 * This source code is NOT MY COPYRIGHTED WORK, and has NO WARRANTY.
 *
 * Refer - a source of an idea:
 *  http://www.kijineko.co.jp/tech/cpptempls/endian
 * */

#ifndef ENDIAN_H
#define ENDIAN_H

#include <algorithm>
#include "cast.hpp"

namespace util {
    namespace endian {
        /*
         *  In a 32-bit machine, the representation of 1 in type int is:
         *
         *      little endian: 01 00 00 00
         *      big endian:    00 00 00 01
         *
         *  therefore the machine is little endian if the first byte is 1
         *  (actually it's 0x01).
         * */
        inline bool is_little() {
            int t = 1;
            return *(util::cast::pointer_cast<char*>(&t)) == 1;
        }
        inline bool is_big() { return !is_little(); }

        // this is slow but nondestructive
        template<typename T> T reverse(T value) {
            char volatile* first = util::cast::pointer_cast<char volatile*>(&value);
            char volatile* last = first + sizeof(T);
            std::reverse(first, last);
            return value;
        }

        // this is destructive but fast
        template<typename T> void fast_reverse(T& value) {
            char volatile* first = util::cast::pointer_cast<char volatile*>(&value);
            char volatile* last = first + sizeof(T);
            std::reverse(first, last);
        }
    }
}

#endif // ENDIAN_H

<|endoftext|>