<commit_before>/*
Copyright (c), Helios
All rights reserved.

Distributed under a permissive license. See COPYING.txt for details.
*/

#include "stdafx.h"
#include "CryptoFilter.h"
#include "Utility.h"

namespace zstreams{

template <typename T>
class GenericCryptoOutputStream : public CryptoSink{
	typename CryptoPP::CBC_Mode<T>::Encryption e;
	std::unique_ptr<CryptoPP::StreamTransformationFilter> filter;

protected:
	CryptoPP::StreamTransformationFilter *get_filter() override{
		return this->filter.get();
	}
public:
	GenericCryptoOutputStream(
			Sink &stream,
			const CryptoPP::SecByteBlock &key,
			const CryptoPP::SecByteBlock &iv): CryptoSink(stream){
		this->e.SetKeyWithIV(key, key.size(), iv.data(), iv.size());
		this->filter.reset(new CryptoPP::StreamTransformationFilter(this->e));
	}
};

Stream<CryptoSink> CryptoSink::create(Algorithm algo, Sink &stream, const CryptoPP::SecByteBlock *key, const CryptoPP::SecByteBlock *iv){
	switch (algo){
		case Algorithm::Rijndael:
			return Stream<GenericCryptoOutputStream<CryptoPP::Rijndael>>(stream, *key, *iv);
		case Algorithm::Serpent:
			return Stream<GenericCryptoOutputStream<CryptoPP::Serpent>>(stream, *key, *iv);
		case Algorithm::Twofish:
			return Stream<GenericCryptoOutputStream<CryptoPP::Twofish>>(stream, *key, *iv);
	}
	zekvok_assert(false);
}

void CryptoSink::work(){
	auto filter = this->get_filter();
	while (true){
		{
			auto segment = this->read();
			if (segment.get_type() == SegmentType::Eof)
				break;
			auto data = segment.get_data();
			filter->Put(data.data, data.size);
		}

		this->flush_filter(filter);
	}
	this->flush_impl();
}

static void flush_filter(StreamProcessor *p, CryptoPP::StreamTransformationFilter *filter){
	while (true){
		auto segment = p->allocate_segment();
		auto data = segment.get_data();
		auto read = filter->Get(data.data, data.size);
		if (!read)
			return;
		segment.trim_to_size(read);
		p->write(segment);
	}
}

void CryptoSink::flush_filter(CryptoPP::StreamTransformationFilter *filter){
	zstreams::flush_filter(this, filter);
}

void CryptoSink::flush_impl(){
	auto filter = this->get_filter();
	if (!this->flushed){
		filter->MessageEnd();
		this->flushed = true;
	}
	this->flush_filter(filter);
}

template <typename T>
class GenericCryptoInputStream : public CryptoSource{
	typename CryptoPP::CBC_Mode<T>::Decryption d;
	std::unique_ptr<CryptoPP::StreamTransformationFilter> filter;

protected:
	CryptoPP::StreamTransformationFilter *get_filter() override{
		return this->filter.get();
	}
public:
	GenericCryptoInputStream(Source &stream, const CryptoPP::SecByteBlock &key, const CryptoPP::SecByteBlock &iv): CryptoSource(stream){
		this->d.SetKeyWithIV(key, key.size(), iv.data(), iv.size());
		this->filter.reset(new CryptoPP::StreamTransformationFilter(this->d));
	}
};

Stream<CryptoSource> CryptoSource::create(
		Algorithm algo,
		Source &stream,
		const CryptoPP::SecByteBlock *key,
		const CryptoPP::SecByteBlock *iv){
	switch (algo){
		case Algorithm::Rijndael:
			return Stream<GenericCryptoInputStream<CryptoPP::Rijndael>>(stream, *key, *iv);
		case Algorithm::Serpent:
			return Stream<GenericCryptoInputStream<CryptoPP::Serpent>>(stream, *key, *iv);
		case Algorithm::Twofish:
			return Stream<GenericCryptoInputStream<CryptoPP::Twofish>>(stream, *key, *iv);
	}
	zekvok_assert(false);
}

void CryptoSource::work(){
	auto filter = this->get_filter();
	bool done = false;

	while (!done){
		{
			auto segment = this->read();
			if (segment.get_type() == SegmentType::Eof){
				filter->MessageEnd();
				done = true;
			}else{
				auto data = segment.get_data();
				filter->Put(data.data, data.size);
			}
		}

		zstreams::flush_filter(this, filter);
	}
	Segment eof(SegmentType::Eof);
	this->write(eof);
}

}
<commit_msg>Fixed innocuous warnings.<commit_after>/*
Copyright (c), Helios
All rights reserved.

Distributed under a permissive license. See COPYING.txt for details.
*/

#include "stdafx.h"
#include "CryptoFilter.h"
#include "Utility.h"

namespace zstreams{

template <typename T>
class GenericCryptoOutputStream : public CryptoSink{
	typename CryptoPP::CBC_Mode<T>::Encryption e;
	std::unique_ptr<CryptoPP::StreamTransformationFilter> filter;

protected:
	CryptoPP::StreamTransformationFilter *get_filter() override{
		return this->filter.get();
	}
public:
	GenericCryptoOutputStream(
			Sink &stream,
			const CryptoPP::SecByteBlock &key,
			const CryptoPP::SecByteBlock &iv): CryptoSink(stream){
		this->e.SetKeyWithIV(key, key.size(), iv.data(), iv.size());
		this->filter.reset(new CryptoPP::StreamTransformationFilter(this->e));
	}
};

Stream<CryptoSink> CryptoSink::create(Algorithm algo, Sink &stream, const CryptoPP::SecByteBlock *key, const CryptoPP::SecByteBlock *iv){
	switch (algo){
		case Algorithm::Rijndael:
			return Stream<GenericCryptoOutputStream<CryptoPP::Rijndael>>(stream, *key, *iv);
		case Algorithm::Serpent:
			return Stream<GenericCryptoOutputStream<CryptoPP::Serpent>>(stream, *key, *iv);
		case Algorithm::Twofish:
			return Stream<GenericCryptoOutputStream<CryptoPP::Twofish>>(stream, *key, *iv);
	}
	zekvok_assert(false);
	return Stream<GenericCryptoOutputStream<CryptoPP::Twofish>>();
}

void CryptoSink::work(){
	auto filter = this->get_filter();
	while (true){
		{
			auto segment = this->read();
			if (segment.get_type() == SegmentType::Eof)
				break;
			auto data = segment.get_data();
			filter->Put(data.data, data.size);
		}

		this->flush_filter(filter);
	}
	this->flush_impl();
}

static void flush_filter(StreamProcessor *p, CryptoPP::StreamTransformationFilter *filter){
	while (true){
		auto segment = p->allocate_segment();
		auto data = segment.get_data();
		auto read = filter->Get(data.data, data.size);
		if (!read)
			return;
		segment.trim_to_size(read);
		p->write(segment);
	}
}

void CryptoSink::flush_filter(CryptoPP::StreamTransformationFilter *filter){
	zstreams::flush_filter(this, filter);
}

void CryptoSink::flush_impl(){
	auto filter = this->get_filter();
	if (!this->flushed){
		filter->MessageEnd();
		this->flushed = true;
	}
	this->flush_filter(filter);
}

template <typename T>
class GenericCryptoInputStream : public CryptoSource{
	typename CryptoPP::CBC_Mode<T>::Decryption d;
	std::unique_ptr<CryptoPP::StreamTransformationFilter> filter;

protected:
	CryptoPP::StreamTransformationFilter *get_filter() override{
		return this->filter.get();
	}
public:
	GenericCryptoInputStream(Source &stream, const CryptoPP::SecByteBlock &key, const CryptoPP::SecByteBlock &iv): CryptoSource(stream){
		this->d.SetKeyWithIV(key, key.size(), iv.data(), iv.size());
		this->filter.reset(new CryptoPP::StreamTransformationFilter(this->d));
	}
};

Stream<CryptoSource> CryptoSource::create(
		Algorithm algo,
		Source &stream,
		const CryptoPP::SecByteBlock *key,
		const CryptoPP::SecByteBlock *iv){
	switch (algo){
		case Algorithm::Rijndael:
			return Stream<GenericCryptoInputStream<CryptoPP::Rijndael>>(stream, *key, *iv);
		case Algorithm::Serpent:
			return Stream<GenericCryptoInputStream<CryptoPP::Serpent>>(stream, *key, *iv);
		case Algorithm::Twofish:
			return Stream<GenericCryptoInputStream<CryptoPP::Twofish>>(stream, *key, *iv);
	}
	zekvok_assert(false);
	return Stream<GenericCryptoInputStream<CryptoPP::Twofish>>();
}

void CryptoSource::work(){
	auto filter = this->get_filter();
	bool done = false;

	while (!done){
		{
			auto segment = this->read();
			if (segment.get_type() == SegmentType::Eof){
				filter->MessageEnd();
				done = true;
			}else{
				auto data = segment.get_data();
				filter->Put(data.data, data.size);
			}
		}

		zstreams::flush_filter(this, filter);
	}
	Segment eof(SegmentType::Eof);
	this->write(eof);
}

}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>

// bitrate index is defined in mp3 structure
// http://www.multiweb.cz/twoinches/mp3inside.htm
#define BITRATE 96000
#define BITRATE_INDEX 7

#define FREQUENCY 48000
#define FREQUENCY_INDEX 1

// broj frame-ova u jednom chunk file-u
#define FRAMES_IN_CHUNK 100
#define FRAMES_OVERHEAD 2

// za frame buffer, nasi frameovi su veliki 313 ili 314 okteta.
#define MAX_FRAME_LENGTH 1000

typedef unsigned char uchar;

// this program works only if mp3 is encoded with
// lame --resample 48 --nores --cbr -b 96 inputfile.mp3 outputfile.mp3
void err(const char *what, int n) {
  fprintf(stderr, "frames: on frame %d: %s\n", n, what);
  exit(1);
}

// padded bit is bit G in the header. note endianes.
// AAAAAAAA   AAABBCCD   EEEEFFGH   IIJJKLMM
// in our endianes:
// AAAAAAAA   AAABBCCD   EEEEFFGH   IIJJKLMM
// f   f      f   b      7   0      0   4
// f   f      e   0      0   0      1   0
int is_padded(uchar *header) {
  return ((header[2] >> 1) & 1);
}

int check_format(uchar *header) {
  // bitrate
  if (!((header[2] >> 4) == BITRATE_INDEX)) {
    return 1;
  }
  // frequency
  if (!(((header[2] >> 2) & 3) == FREQUENCY_INDEX)) {
    return 2;
  }
  if (!(header[1] & 1)) {
    return 3;
  }
  return 0;
}

void assert_format(uchar *header, int n) {
  int sol = check_format(header);
  if (sol == 1) err("bitrate is not valid.", n);
  if (sol == 2) err("sampling freq is not valid.", n);
  if (sol == 3) err("we have crc protection and we don't want it.", n);
}

// every header starts with 11 one bits (aligned to a whole byte?)
int seek_to_frame_start(FILE *fp, int n) {
  uchar header[4];
  for (;;) {
    int byte = fgetc(fp);
    if (byte == EOF) {
      return -1;
    }
    if (byte == 0xff) {
      int next = fgetc(fp);
      if ((next >> 5) == 7) {
        ungetc(next, fp);
        ungetc(byte, fp);
        // output only frames with correct header.
        fread(header, 4, 1, fp);
        fseek(fp, ftell(fp) - 4, SEEK_SET);
        if (check_format(header)) {
          fprintf(stderr, "found frame but with wrong audio params\n");
          fgetc(fp);
          continue;
        }
        return 0;
      } else {
        ungetc(next, fp);
      }
    }
    if (n > 0) {
      err("next frame sync expected.", n);
    }
  }
}

// load frame into char* and return frame size.
int load_frame(FILE *fp, int n, char *frame) {
  uchar header[4];
  if (seek_to_frame_start(fp, n) == -1) {
    return -1;
  }

  // read and unread header info.
  fread(header, 4, 1, fp);
  fseek(fp, ftell(fp) - 4, SEEK_SET);

  // make sure that sampling freq and bitrates are OK.
  assert_format(header, n);

  // calculate frame length.
  int paddingbit = is_padded(header);
  int framelength = (144 * BITRATE / FREQUENCY) + paddingbit;

  if (fread(frame, framelength, 1, fp) != 1) {
    err("couldn't read whole frame (fread).", n);
  }

  return framelength;
}

int last_opened = -1;

// lots of open operations, but it isn't botleneck
void write_to(int chunk_num, int bytes, char *buffer, int n, long long chunk_folder) {
  static char filename[1<<16];
  FILE *out;
  snprintf(filename, sizeof filename, "%lld/%d.mp3", chunk_folder, chunk_num);

  if (chunk_num > last_opened) {
    out = fopen(filename, "w");
    last_opened = chunk_num;
  } else {
    out = fopen(filename, "a");
  }

  if (fwrite(buffer, bytes, 1, out) != 1) {
    err("error while writing chunk.", n);
  }
  fclose(out);
}

int chunkify(FILE *fp, long long chunk_folder) {
  static char buffer[MAX_FRAME_LENGTH];
  int framelength, n;

  for (n = 0; ; ++n) {
    if ((framelength = load_frame(fp, n, buffer)) == -1) {
      break;
    }
    write_to(n / FRAMES_IN_CHUNK, framelength, buffer, n, chunk_folder);
    // write overhead
    if (n >= FRAMES_IN_CHUNK && n % FRAMES_IN_CHUNK < FRAMES_OVERHEAD) {
      write_to(n / FRAMES_IN_CHUNK - 1, framelength, buffer, n, chunk_folder);
    }
  }

  return n / FRAMES_IN_CHUNK + 1;
}

int main(int argc, char **argv) {
  long long chunk_folder;
  sscanf(argv[2], "%lld", &chunk_folder);

  FILE *in = fopen(argv[1], "r");
  printf("%d\n", chunkify(in, chunk_folder));
  fclose(in);
  return 0;
}

<commit_msg>let's not give up that easily<commit_after>#include <cstdio>
#include <cstdlib>

// bitrate index is defined in mp3 structure
// http://www.multiweb.cz/twoinches/mp3inside.htm
#define BITRATE 96000
#define BITRATE_INDEX 7

#define FREQUENCY 48000
#define FREQUENCY_INDEX 1

// broj frame-ova u jednom chunk file-u
#define FRAMES_IN_CHUNK 100
#define FRAMES_OVERHEAD 2

// za frame buffer, nasi frameovi su veliki 313 ili 314 okteta.
#define MAX_FRAME_LENGTH 1000

typedef unsigned char uchar;

// this program works only if mp3 is encoded with
// lame --resample 48 --nores --cbr -b 96 inputfile.mp3 outputfile.mp3
void err(const char *what, int n) {
  fprintf(stderr, "frames: on frame %d: %s\n", n, what);
  exit(1);
}

// padded bit is bit G in the header. note endianes.
// AAAAAAAA   AAABBCCD   EEEEFFGH   IIJJKLMM
// in our endianes:
// AAAAAAAA   AAABBCCD   EEEEFFGH   IIJJKLMM
// f   f      f   b      7   0      0   4
// f   f      e   0      0   0      1   0
int is_padded(uchar *header) {
  return ((header[2] >> 1) & 1);
}

int check_format(uchar *header) {
  // bitrate
  if (!((header[2] >> 4) == BITRATE_INDEX)) {
    return 1;
  }
  // frequency
  if (!(((header[2] >> 2) & 3) == FREQUENCY_INDEX)) {
    return 2;
  }
  if (!(header[1] & 1)) {
    return 3;
  }
  return 0;
}

void assert_format(uchar *header, int n) {
  int sol = check_format(header);
  if (sol == 1) err("bitrate is not valid.", n);
  if (sol == 2) err("sampling freq is not valid.", n);
  if (sol == 3) err("we have crc protection and we don't want it.", n);
}

// every header starts with 11 one bits (aligned to a whole byte?)
int seek_to_frame_start(FILE *fp, int n) {
  uchar header[4];
  for (;;) {
    int byte = fgetc(fp);
    if (byte == EOF) {
      return -1;
    }
    if (byte == 0xff) {
      int next = fgetc(fp);
      if ((next >> 5) == 7) {
        ungetc(next, fp);
        ungetc(byte, fp);
        // output only frames with correct header.
        fread(header, 4, 1, fp);
        fseek(fp, ftell(fp) - 4, SEEK_SET);
        if (check_format(header)) {
          fprintf(stderr, "found frame but with wrong audio params\n");
          fgetc(fp);
          continue;
        }
        return 0;
      } else {
        ungetc(next, fp);
      }
    }
  }
}

// load frame into char* and return frame size.
int load_frame(FILE *fp, int n, char *frame) {
  uchar header[4];
  if (seek_to_frame_start(fp, n) == -1) {
    return -1;
  }

  // read and unread header info.
  fread(header, 4, 1, fp);
  fseek(fp, ftell(fp) - 4, SEEK_SET);

  // make sure that sampling freq and bitrates are OK.
  assert_format(header, n);

  // calculate frame length.
  int paddingbit = is_padded(header);
  int framelength = (144 * BITRATE / FREQUENCY) + paddingbit;

  if (fread(frame, framelength, 1, fp) != 1) {
    err("couldn't read whole frame (fread).", n);
  }

  return framelength;
}

int last_opened = -1;

// lots of open operations, but it isn't botleneck
void write_to(int chunk_num, int bytes, char *buffer, int n, long long chunk_folder) {
  static char filename[1<<16];
  FILE *out;
  snprintf(filename, sizeof filename, "%lld/%d.mp3", chunk_folder, chunk_num);

  if (chunk_num > last_opened) {
    out = fopen(filename, "w");
    last_opened = chunk_num;
  } else {
    out = fopen(filename, "a");
  }

  if (fwrite(buffer, bytes, 1, out) != 1) {
    err("error while writing chunk.", n);
  }
  fclose(out);
}

int chunkify(FILE *fp, long long chunk_folder) {
  static char buffer[MAX_FRAME_LENGTH];
  int framelength, n;

  for (n = 0; ; ++n) {
    if ((framelength = load_frame(fp, n, buffer)) == -1) {
      break;
    }
    write_to(n / FRAMES_IN_CHUNK, framelength, buffer, n, chunk_folder);
    // write overhead
    if (n >= FRAMES_IN_CHUNK && n % FRAMES_IN_CHUNK < FRAMES_OVERHEAD) {
      write_to(n / FRAMES_IN_CHUNK - 1, framelength, buffer, n, chunk_folder);
    }
  }

  return n / FRAMES_IN_CHUNK + 1;
}

int main(int argc, char **argv) {
  long long chunk_folder;
  sscanf(argv[2], "%lld", &chunk_folder);

  FILE *in = fopen(argv[1], "r");
  printf("%d\n", chunkify(in, chunk_folder));
  fclose(in);
  return 0;
}

<|endoftext|>


<commit_before>//==- DeadStores.cpp - Check for stores to dead variables --------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This files defines a DeadStores, a flow-sensitive checker that looks for
//  stores to variables that are no longer live.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Expr.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/LiveVariables.h"
#include "clang/AST/CFG.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"

using namespace clang;

namespace {

class DeadStoreObserver : public LiveVariablesObserver {
  Preprocessor& PP;
public:
  DeadStoreObserver(Preprocessor& pp) : PP(pp) {}
  virtual ~DeadStoreObserver() {}

  virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& Live) {
    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
      // Is this an assignment?
      if (!B->isAssignmentOp())
        return;

      // Is this an assignment to a variable?
      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
        // Is the variable live?
        if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) {
          SourceRange R = B->getRHS()->getSourceRange();
          PP.getDiagnostics().Report(DR->getSourceRange().Begin(),
                                     diag::warn_dead_store, 0, 0,
                                     &R,1);

        }
    }
    else if(DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
      // Iterate through the decls.  Warn if any of them (which have
      // initializers) are not live.
      for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
                    V = cast_or_null<VarDecl>(V->getNextDeclarator()))
        if (Expr* E = V->getInit())
          if (!L.isLive(Live,V)) {
            SourceRange R = E->getSourceRange();
            PP.getDiagnostics().Report(V->getLocation(),
                                       diag::warn_dead_store, 0, 0,
                                       &R,1);
          }
    }
  }
};

} // end anonymous namespace

namespace clang {

void CheckDeadStores(CFG& cfg, LiveVariables& L, Preprocessor& PP) {
  DeadStoreObserver A(PP);

  for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
    L.runOnBlock(&(*I),&A);
}

void CheckDeadStores(CFG& cfg, Preprocessor& PP) {
  LiveVariables L;
  L.runOnCFG(cfg);
  CheckDeadStores(cfg,L,PP);
}

} // end namespace clang
<commit_msg>For looking at "dead stores" in declarations, we now check to see if the assigned value is a constant expression, e.g.:<commit_after>//==- DeadStores.cpp - Check for stores to dead variables --------*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This files defines a DeadStores, a flow-sensitive checker that looks for
//  stores to variables that are no longer live.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Expr.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/LiveVariables.h"
#include "clang/AST/CFG.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTContext.h"

using namespace clang;

namespace {

class DeadStoreObserver : public LiveVariablesObserver {
  Preprocessor& PP;
  ASTContext Ctx;
public:
  DeadStoreObserver(Preprocessor& pp) :
    PP(pp), Ctx(PP.getTargetInfo(), PP.getIdentifierTable()) {}

  virtual ~DeadStoreObserver() {}

  virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& Live) {
    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
      // Is this an assignment?
      if (!B->isAssignmentOp())
        return;

      // Is this an assignment to a variable?
      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
        // Is the variable live?
        if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) {
          SourceRange R = B->getRHS()->getSourceRange();
          PP.getDiagnostics().Report(DR->getSourceRange().Begin(),
                                     diag::warn_dead_store, 0, 0,
                                     &R,1);

        }
    }
    else if(DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
      // Iterate through the decls.  Warn if any of them (which have
      // initializers) are not live.
      for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
                    V = cast_or_null<VarDecl>(V->getNextDeclarator()))
        if (Expr* E = V->getInit())
          if (!L.isLive(Live,V))
            // Special case: check for initializations with constants.
            //
            //  e.g. : int x = 0;
            //
            // If x is EVER assigned a new value later, don't issue
            // a warning.  This is because such initialization can be
            // due to defensive programming.
            if (!E->isConstantExpr(Ctx,NULL) ||
                L.getVarInfo(V).Kills.size() == 0) {
              // Flag a warning.
              SourceRange R = E->getSourceRange();
              PP.getDiagnostics().Report(V->getLocation(),
                                         diag::warn_dead_store, 0, 0,
                                         &R,1);
            }
    }
  }
};

} // end anonymous namespace

namespace clang {

void CheckDeadStores(CFG& cfg, LiveVariables& L, Preprocessor& PP) {
  DeadStoreObserver A(PP);

  for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
    L.runOnBlock(&(*I),&A);
}

void CheckDeadStores(CFG& cfg, Preprocessor& PP) {
  LiveVariables L;
  L.runOnCFG(cfg);
  CheckDeadStores(cfg,L,PP);
}

} // end namespace clang
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "nonlinear_implicit_system.h"
#include "diff_solver.h"
#include "equation_systems.h"
#include "libmesh_logging.h"
#include "linear_solver.h"
#include "nonlinear_solver.h"
#include "numeric_vector.h"
#include "parameter_vector.h"
#include "sparse_matrix.h"

namespace libMesh
{

// ------------------------------------------------------------
// NonlinearImplicitSystem implementation
NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems& es,
						  const std::string& name,
						  const unsigned int number) :

  Parent                    (es, name, number),
  nonlinear_solver          (NonlinearSolver<Number>::build(*this)),
  diff_solver               (NULL),
  _n_nonlinear_iterations   (0),
  _final_nonlinear_residual (1.e20)
{
  // Set default parameters
  // These were chosen to match the Petsc defaults
  es.parameters.set<Real>        ("linear solver tolerance") = 1e-5;
  es.parameters.set<Real>        ("linear solver minimum tolerance") = 1e-5;
  es.parameters.set<unsigned int>("linear solver maximum iterations") = 10000;

  es.parameters.set<unsigned int>("nonlinear solver maximum iterations") = 50;
  es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") = 10000;

  es.parameters.set<Real>("nonlinear solver absolute residual tolerance") = 1e-50;
  es.parameters.set<Real>("nonlinear solver relative residual tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver absolute step tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;
}

NonlinearImplicitSystem::~NonlinearImplicitSystem ()
{
  // Clear data
  this->clear();
}

void NonlinearImplicitSystem::clear ()
{
  // clear the nonlinear solver
  nonlinear_solver->clear();

  // clear the parent data
  Parent::clear();
}

void NonlinearImplicitSystem::reinit ()
{
  // re-initialize the nonlinear solver interface
  nonlinear_solver->clear();

  if (diff_solver.get())
    diff_solver->reinit();

  // initialize parent data
  Parent::reinit();
}

void NonlinearImplicitSystem::set_solver_parameters ()
{
  // Get a reference to the EquationSystems
  const EquationSystems& es =
    this->get_equation_systems();

  // Get the user-specifiied nonlinear solver tolerances
  const unsigned int maxits =
    es.parameters.get<unsigned int>("nonlinear solver maximum iterations");

  const unsigned int maxfuncs =
    es.parameters.get<unsigned int>("nonlinear solver maximum function evaluations");

  const Real abs_resid_tol =
    es.parameters.get<Real>("nonlinear solver absolute residual tolerance");

  const Real rel_resid_tol =
    es.parameters.get<Real>("nonlinear solver relative residual tolerance");

  const Real abs_step_tol =
    es.parameters.get<Real>("nonlinear solver absolute step tolerance");

  const Real rel_step_tol =
    es.parameters.get<Real>("nonlinear solver relative step tolerance");

  // Get the user-specified linear solver toleranaces
  const unsigned int maxlinearits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const Real linear_tol =
    es.parameters.get<Real>("linear solver tolerance");

  const Real linear_min_tol =
    es.parameters.get<Real>("linear solver minimum tolerance");

  // Set all the parameters on the NonlinearSolver
  nonlinear_solver->max_nonlinear_iterations = maxits;
  nonlinear_solver->max_function_evaluations = maxfuncs;
  nonlinear_solver->absolute_residual_tolerance = abs_resid_tol;
  nonlinear_solver->relative_residual_tolerance = rel_resid_tol;
  nonlinear_solver->absolute_step_tolerance = abs_step_tol;
  nonlinear_solver->relative_step_tolerance = rel_step_tol;
  nonlinear_solver->max_linear_iterations = maxlinearits;
  nonlinear_solver->initial_linear_tolerance = linear_tol;
  nonlinear_solver->minimum_linear_tolerance = linear_min_tol;

  if (diff_solver.get())
    {
      diff_solver->max_nonlinear_iterations = maxits;
      diff_solver->absolute_residual_tolerance = abs_resid_tol;
      diff_solver->relative_residual_tolerance = rel_resid_tol;
      diff_solver->absolute_step_tolerance = abs_step_tol;
      diff_solver->relative_step_tolerance = rel_step_tol;
      diff_solver->max_linear_iterations = maxlinearits;
      diff_solver->initial_linear_tolerance = linear_tol;
      diff_solver->minimum_linear_tolerance = linear_min_tol;
    }
}

void NonlinearImplicitSystem::solve ()
{
  // Log how long the nonlinear solve takes.
  START_LOG("solve()", "System");

  this->set_solver_parameters();

  if (diff_solver.get())
    {
      diff_solver->solve();

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = diff_solver->total_outer_iterations();
      _final_nonlinear_residual = 0.; // FIXME - support this!
    }
  else
    {
      // Solve the nonlinear system.
      const std::pair<unsigned int, Real> rval =
        nonlinear_solver->solve (*matrix, *solution, *rhs,
			         nonlinear_solver->relative_residual_tolerance,
                                 nonlinear_solver->max_linear_iterations);

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = rval.first;
      _final_nonlinear_residual = rval.second;
    }

  // Stop logging the nonlinear solve
  STOP_LOG("solve()", "System");

  // Update the system after the solve
  this->update();
}

std::pair<unsigned int, Real> NonlinearImplicitSystem::get_linear_solve_parameters() const
{
  if (diff_solver.get())
    return std::make_pair(this->diff_solver->max_linear_iterations,
                        this->diff_solver->relative_residual_tolerance);
  return std::make_pair(this->nonlinear_solver->max_linear_iterations,
                        this->nonlinear_solver->relative_residual_tolerance);
}

void NonlinearImplicitSystem::assembly(bool,
				       bool get_jacobian)
{
  if (get_jacobian)
    {
      if (nonlinear_solver->jacobian != NULL)
        nonlinear_solver->jacobian (*current_local_solution.get(), *matrix, *this);
      else if (nonlinear_solver->matvec != NULL)
        nonlinear_solver->matvec (*current_local_solution.get(), NULL, matrix, *this);
      else libmesh_error();
    }
}

} // namespace libMesh
<commit_msg>Fixes for NonlinearImplicitSystem::assembly()<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ includes

// Local includes
#include "nonlinear_implicit_system.h"
#include "diff_solver.h"
#include "equation_systems.h"
#include "libmesh_logging.h"
#include "linear_solver.h"
#include "nonlinear_solver.h"
#include "numeric_vector.h"
#include "parameter_vector.h"
#include "sparse_matrix.h"

namespace libMesh
{

// ------------------------------------------------------------
// NonlinearImplicitSystem implementation
NonlinearImplicitSystem::NonlinearImplicitSystem (EquationSystems& es,
						  const std::string& name,
						  const unsigned int number) :

  Parent                    (es, name, number),
  nonlinear_solver          (NonlinearSolver<Number>::build(*this)),
  diff_solver               (NULL),
  _n_nonlinear_iterations   (0),
  _final_nonlinear_residual (1.e20)
{
  // Set default parameters
  // These were chosen to match the Petsc defaults
  es.parameters.set<Real>        ("linear solver tolerance") = 1e-5;
  es.parameters.set<Real>        ("linear solver minimum tolerance") = 1e-5;
  es.parameters.set<unsigned int>("linear solver maximum iterations") = 10000;

  es.parameters.set<unsigned int>("nonlinear solver maximum iterations") = 50;
  es.parameters.set<unsigned int>("nonlinear solver maximum function evaluations") = 10000;

  es.parameters.set<Real>("nonlinear solver absolute residual tolerance") = 1e-50;
  es.parameters.set<Real>("nonlinear solver relative residual tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver absolute step tolerance") = 1e-8;
  es.parameters.set<Real>("nonlinear solver relative step tolerance") = 1e-8;
}

NonlinearImplicitSystem::~NonlinearImplicitSystem ()
{
  // Clear data
  this->clear();
}

void NonlinearImplicitSystem::clear ()
{
  // clear the nonlinear solver
  nonlinear_solver->clear();

  // clear the parent data
  Parent::clear();
}

void NonlinearImplicitSystem::reinit ()
{
  // re-initialize the nonlinear solver interface
  nonlinear_solver->clear();

  if (diff_solver.get())
    diff_solver->reinit();

  // initialize parent data
  Parent::reinit();
}

void NonlinearImplicitSystem::set_solver_parameters ()
{
  // Get a reference to the EquationSystems
  const EquationSystems& es =
    this->get_equation_systems();

  // Get the user-specifiied nonlinear solver tolerances
  const unsigned int maxits =
    es.parameters.get<unsigned int>("nonlinear solver maximum iterations");

  const unsigned int maxfuncs =
    es.parameters.get<unsigned int>("nonlinear solver maximum function evaluations");

  const Real abs_resid_tol =
    es.parameters.get<Real>("nonlinear solver absolute residual tolerance");

  const Real rel_resid_tol =
    es.parameters.get<Real>("nonlinear solver relative residual tolerance");

  const Real abs_step_tol =
    es.parameters.get<Real>("nonlinear solver absolute step tolerance");

  const Real rel_step_tol =
    es.parameters.get<Real>("nonlinear solver relative step tolerance");

  // Get the user-specified linear solver toleranaces
  const unsigned int maxlinearits =
    es.parameters.get<unsigned int>("linear solver maximum iterations");

  const Real linear_tol =
    es.parameters.get<Real>("linear solver tolerance");

  const Real linear_min_tol =
    es.parameters.get<Real>("linear solver minimum tolerance");

  // Set all the parameters on the NonlinearSolver
  nonlinear_solver->max_nonlinear_iterations = maxits;
  nonlinear_solver->max_function_evaluations = maxfuncs;
  nonlinear_solver->absolute_residual_tolerance = abs_resid_tol;
  nonlinear_solver->relative_residual_tolerance = rel_resid_tol;
  nonlinear_solver->absolute_step_tolerance = abs_step_tol;
  nonlinear_solver->relative_step_tolerance = rel_step_tol;
  nonlinear_solver->max_linear_iterations = maxlinearits;
  nonlinear_solver->initial_linear_tolerance = linear_tol;
  nonlinear_solver->minimum_linear_tolerance = linear_min_tol;

  if (diff_solver.get())
    {
      diff_solver->max_nonlinear_iterations = maxits;
      diff_solver->absolute_residual_tolerance = abs_resid_tol;
      diff_solver->relative_residual_tolerance = rel_resid_tol;
      diff_solver->absolute_step_tolerance = abs_step_tol;
      diff_solver->relative_step_tolerance = rel_step_tol;
      diff_solver->max_linear_iterations = maxlinearits;
      diff_solver->initial_linear_tolerance = linear_tol;
      diff_solver->minimum_linear_tolerance = linear_min_tol;
    }
}

void NonlinearImplicitSystem::solve ()
{
  // Log how long the nonlinear solve takes.
  START_LOG("solve()", "System");

  this->set_solver_parameters();

  if (diff_solver.get())
    {
      diff_solver->solve();

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = diff_solver->total_outer_iterations();
      _final_nonlinear_residual = 0.; // FIXME - support this!
    }
  else
    {
      // Solve the nonlinear system.
      const std::pair<unsigned int, Real> rval =
        nonlinear_solver->solve (*matrix, *solution, *rhs,
			         nonlinear_solver->relative_residual_tolerance,
                                 nonlinear_solver->max_linear_iterations);

      // Store the number of nonlinear iterations required to
      // solve and the final residual.
      _n_nonlinear_iterations   = rval.first;
      _final_nonlinear_residual = rval.second;
    }

  // Stop logging the nonlinear solve
  STOP_LOG("solve()", "System");

  // Update the system after the solve
  this->update();
}

std::pair<unsigned int, Real> NonlinearImplicitSystem::get_linear_solve_parameters() const
{
  if (diff_solver.get())
    return std::make_pair(this->diff_solver->max_linear_iterations,
                        this->diff_solver->relative_residual_tolerance);
  return std::make_pair(this->nonlinear_solver->max_linear_iterations,
                        this->nonlinear_solver->relative_residual_tolerance);
}

void NonlinearImplicitSystem::assembly(bool get_residual,
				       bool get_jacobian)
{
  // Get current_local_solution in sync
  this->update();

  if (get_jacobian)
    {
      if (nonlinear_solver->jacobian != NULL)
        nonlinear_solver->jacobian (*current_local_solution.get(), *matrix, *this);
      else if (nonlinear_solver->matvec != NULL)
        nonlinear_solver->matvec (*current_local_solution.get(), get_residual?rhs:NULL, matrix, *this);
      else libmesh_error();
    }

  if (get_residual)
    {
      if (nonlinear_solver->residual != NULL)
        nonlinear_solver->residual (*current_local_solution.get(), *rhs, *this);
      else if (nonlinear_solver->matvec != NULL)
        {
          // we might have already grabbed the residual and jacobian together
          if (!get_jacobian)
            nonlinear_solver->matvec (*current_local_solution.get(), rhs, NULL, *this);
        }
      else
        libmesh_error();
    }
  else
    libmesh_assert(false);  // I can't believe you really wanted to assemble *nothing*
}

} // namespace libMesh
<|endoftext|>


<commit_before>//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
//
//                     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 simple N^2 alias analysis accuracy evaluator.
// Basically, for each function in the program, it simply queries to see how the
// alias analysis implementation answers alias queries between each pair of
// pointers in the function.
//
// This is inspired and adapted from code by: Naveen Neelakantam, Francesco
// Spadini, and Wojciech Stryjewski.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SetVector.h"
using namespace llvm;

static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden);

static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden);
static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden);
static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden);

static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden);
static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);

namespace {
  class AAEval : public FunctionPass {
    unsigned NoAlias, MayAlias, MustAlias;
    unsigned NoModRef, Mod, Ref, ModRef;

  public:
    static char ID; // Pass identification, replacement for typeid
    AAEval() : FunctionPass(&ID) {}

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<AliasAnalysis>();
      AU.setPreservesAll();
    }

    bool doInitialization(Module &M) {
      NoAlias = MayAlias = MustAlias = 0;
      NoModRef = Mod = Ref = ModRef = 0;

      if (PrintAll) {
        PrintNoAlias = PrintMayAlias = PrintMustAlias = true;
        PrintNoModRef = PrintMod = PrintRef = PrintModRef = true;
      }
      return false;
    }

    bool runOnFunction(Function &F);
    bool doFinalization(Module &M);
  };
}

char AAEval::ID = 0;
static RegisterPass<AAEval>
X("aa-eval", "Exhaustive Alias Analysis Precision Evaluator", false, true);

FunctionPass *llvm::createAAEvalPass() { return new AAEval(); }

static void PrintResults(const char *Msg, bool P, const Value *V1,
                         const Value *V2, const Module *M) {
  if (P) {
    std::string o1, o2;
    {
      raw_string_ostream os1(o1), os2(o2);
      WriteAsOperand(os1, V1, true, M);
      WriteAsOperand(os2, V2, true, M);
    }

    if (o2 < o1)
      std::swap(o1, o2);
    errs() << "  " << Msg << ":\t"
           << o1 << ", "
           << o2 << "\n";
  }
}

static inline void
PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr,
                   Module *M) {
  if (P) {
    errs() << "  " << Msg << ":  Ptr: ";
    WriteAsOperand(errs(), Ptr, true, M);
    errs() << "\t<->" << *I << '\n';
  }
}

bool AAEval::runOnFunction(Function &F) {
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();

  SetVector<Value *> Pointers;
  SetVector<CallSite> CallSites;

  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
    if (I->getType()->isPointerTy())    // Add all pointer arguments
      Pointers.insert(I);

  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
    if (I->getType()->isPointerTy()) // Add all pointer instructions
      Pointers.insert(&*I);
    Instruction &Inst = *I;
    User::op_iterator OI = Inst.op_begin();
    CallSite CS = CallSite::get(&Inst);
    if (CS.getInstruction() &&
        isa<Function>(CS.getCalledValue()))
      ++OI;  // Skip actual functions for direct function calls.
    for (; OI != Inst.op_end(); ++OI)
      if ((*OI)->getType()->isPointerTy() && !isa<ConstantPointerNull>(*OI))
        Pointers.insert(*OI);

    if (CS.getInstruction()) CallSites.insert(CS);
  }

  if (PrintNoAlias || PrintMayAlias || PrintMustAlias ||
      PrintNoModRef || PrintMod || PrintRef || PrintModRef)
    errs() << "Function: " << F.getName() << ": " << Pointers.size()
           << " pointers, " << CallSites.size() << " call sites\n";

  // iterate over the worklist, and run the full (n^2)/2 disambiguations
  for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
       I1 != E; ++I1) {
    unsigned I1Size = ~0u;
    const Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
    if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy);

    for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
      unsigned I2Size = ~0u;
      const Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType();
      if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy);

      switch (AA.alias(*I1, I1Size, *I2, I2Size)) {
      case AliasAnalysis::NoAlias:
        PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent());
        ++NoAlias; break;
      case AliasAnalysis::MayAlias:
        PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent());
        ++MayAlias; break;
      case AliasAnalysis::MustAlias:
        PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent());
        ++MustAlias; break;
      default:
        errs() << "Unknown alias query result!\n";
      }
    }
  }

  // Mod/ref alias analysis: compare all pairs of calls and values
  for (SetVector<CallSite>::iterator C = CallSites.begin(),
         Ce = CallSites.end(); C != Ce; ++C) {
    Instruction *I = C->getInstruction();

    for (SetVector<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end();
         V != Ve; ++V) {
      unsigned Size = ~0u;
      const Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
      if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy);

      switch (AA.getModRefInfo(*C, *V, Size)) {
      case AliasAnalysis::NoModRef:
        PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent());
        ++NoModRef; break;
      case AliasAnalysis::Mod:
        PrintModRefResults("     Mod", PrintMod, I, *V, F.getParent());
        ++Mod; break;
      case AliasAnalysis::Ref:
        PrintModRefResults("     Ref", PrintRef, I, *V, F.getParent());
        ++Ref; break;
      case AliasAnalysis::ModRef:
        PrintModRefResults("  ModRef", PrintModRef, I, *V, F.getParent());
        ++ModRef; break;
      default:
        errs() << "Unknown alias query result!\n";
      }
    }
  }

  return false;
}

static void PrintPercent(unsigned Num, unsigned Sum) {
  errs() << "(" << Num*100ULL/Sum << "."
         << ((Num*1000ULL/Sum) % 10) << "%)\n";
}

bool AAEval::doFinalization(Module &M) {
  unsigned AliasSum = NoAlias + MayAlias + MustAlias;
  errs() << "===== Alias Analysis Evaluator Report =====\n";
  if (AliasSum == 0) {
    errs() << "  Alias Analysis Evaluator Summary: No pointers!\n";
  } else {
    errs() << "  " << AliasSum << " Total Alias Queries Performed\n";
    errs() << "  " << NoAlias << " no alias responses ";
    PrintPercent(NoAlias, AliasSum);
    errs() << "  " << MayAlias << " may alias responses ";
    PrintPercent(MayAlias, AliasSum);
    errs() << "  " << MustAlias << " must alias responses ";
    PrintPercent(MustAlias, AliasSum);
    errs() << "  Alias Analysis Evaluator Pointer Alias Summary: "
           << NoAlias*100/AliasSum  << "%/" << MayAlias*100/AliasSum << "%/"
           << MustAlias*100/AliasSum << "%\n";
  }

  // Display the summary for mod/ref analysis
  unsigned ModRefSum = NoModRef + Mod + Ref + ModRef;
  if (ModRefSum == 0) {
    errs() << "  Alias Analysis Mod/Ref Evaluator Summary: no mod/ref!\n";
  } else {
    errs() << "  " << ModRefSum << " Total ModRef Queries Performed\n";
    errs() << "  " << NoModRef << " no mod/ref responses ";
    PrintPercent(NoModRef, ModRefSum);
    errs() << "  " << Mod << " mod responses ";
    PrintPercent(Mod, ModRefSum);
    errs() << "  " << Ref << " ref responses ";
    PrintPercent(Ref, ModRefSum);
    errs() << "  " << ModRef << " mod & ref responses ";
    PrintPercent(ModRef, ModRefSum);
    errs() << "  Alias Analysis Evaluator Mod/Ref Summary: "
           << NoModRef*100/ModRefSum  << "%/" << Mod*100/ModRefSum << "%/"
           << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n";
  }

  return false;
}
<commit_msg>clean up algorithm and remove operand order assumptions<commit_after>//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
//
//                     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 simple N^2 alias analysis accuracy evaluator.
// Basically, for each function in the program, it simply queries to see how the
// alias analysis implementation answers alias queries between each pair of
// pointers in the function.
//
// This is inspired and adapted from code by: Naveen Neelakantam, Francesco
// Spadini, and Wojciech Stryjewski.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SetVector.h"
using namespace llvm;

static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden);

static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden);
static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden);
static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden);

static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden);
static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);

namespace {
  class AAEval : public FunctionPass {
    unsigned NoAlias, MayAlias, MustAlias;
    unsigned NoModRef, Mod, Ref, ModRef;

  public:
    static char ID; // Pass identification, replacement for typeid
    AAEval() : FunctionPass(&ID) {}

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<AliasAnalysis>();
      AU.setPreservesAll();
    }

    bool doInitialization(Module &M) {
      NoAlias = MayAlias = MustAlias = 0;
      NoModRef = Mod = Ref = ModRef = 0;

      if (PrintAll) {
        PrintNoAlias = PrintMayAlias = PrintMustAlias = true;
        PrintNoModRef = PrintMod = PrintRef = PrintModRef = true;
      }
      return false;
    }

    bool runOnFunction(Function &F);
    bool doFinalization(Module &M);
  };
}

char AAEval::ID = 0;
static RegisterPass<AAEval>
X("aa-eval", "Exhaustive Alias Analysis Precision Evaluator", false, true);

FunctionPass *llvm::createAAEvalPass() { return new AAEval(); }

static void PrintResults(const char *Msg, bool P, const Value *V1,
                         const Value *V2, const Module *M) {
  if (P) {
    std::string o1, o2;
    {
      raw_string_ostream os1(o1), os2(o2);
      WriteAsOperand(os1, V1, true, M);
      WriteAsOperand(os2, V2, true, M);
    }

    if (o2 < o1)
      std::swap(o1, o2);
    errs() << "  " << Msg << ":\t"
           << o1 << ", "
           << o2 << "\n";
  }
}

static inline void
PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr,
                   Module *M) {
  if (P) {
    errs() << "  " << Msg << ":  Ptr: ";
    WriteAsOperand(errs(), Ptr, true, M);
    errs() << "\t<->" << *I << '\n';
  }
}

static inline bool isInterestingPointer(Value *V) {
  return V->getType()->isPointerTy()
      && !isa<ConstantPointerNull>(V);
}

bool AAEval::runOnFunction(Function &F) {
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();

  SetVector<Value *> Pointers;
  SetVector<CallSite> CallSites;

  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
    if (I->getType()->isPointerTy())    // Add all pointer arguments.
      Pointers.insert(I);

  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
    if (I->getType()->isPointerTy()) // Add all pointer instructions.
      Pointers.insert(&*I);
    Instruction &Inst = *I;
    CallSite CS = CallSite::get(&Inst);
    if (CS) {
      Value *Callee = CS.getCalledValue();
      // Skip actual functions for direct function calls.
      if (!isa<Function>(Callee) && isInterestingPointer(Callee))
        Pointers.insert(Callee);
      // Consider formals.
      for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
           AI != AE; ++AI)
        if (isInterestingPointer(*AI))
          Pointers.insert(*AI);
    } else {
      // Consider all operands.
      for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end();
           OI != OE; ++OI)
        if (isInterestingPointer(*OI))
          Pointers.insert(*OI);
    }

    if (CS.getInstruction()) CallSites.insert(CS);
  }

  if (PrintNoAlias || PrintMayAlias || PrintMustAlias ||
      PrintNoModRef || PrintMod || PrintRef || PrintModRef)
    errs() << "Function: " << F.getName() << ": " << Pointers.size()
           << " pointers, " << CallSites.size() << " call sites\n";

  // iterate over the worklist, and run the full (n^2)/2 disambiguations
  for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
       I1 != E; ++I1) {
    unsigned I1Size = ~0u;
    const Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
    if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy);

    for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
      unsigned I2Size = ~0u;
      const Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType();
      if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy);

      switch (AA.alias(*I1, I1Size, *I2, I2Size)) {
      case AliasAnalysis::NoAlias:
        PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent());
        ++NoAlias; break;
      case AliasAnalysis::MayAlias:
        PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent());
        ++MayAlias; break;
      case AliasAnalysis::MustAlias:
        PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent());
        ++MustAlias; break;
      default:
        errs() << "Unknown alias query result!\n";
      }
    }
  }

  // Mod/ref alias analysis: compare all pairs of calls and values
  for (SetVector<CallSite>::iterator C = CallSites.begin(),
         Ce = CallSites.end(); C != Ce; ++C) {
    Instruction *I = C->getInstruction();

    for (SetVector<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end();
         V != Ve; ++V) {
      unsigned Size = ~0u;
      const Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
      if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy);

      switch (AA.getModRefInfo(*C, *V, Size)) {
      case AliasAnalysis::NoModRef:
        PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent());
        ++NoModRef; break;
      case AliasAnalysis::Mod:
        PrintModRefResults("     Mod", PrintMod, I, *V, F.getParent());
        ++Mod; break;
      case AliasAnalysis::Ref:
        PrintModRefResults("     Ref", PrintRef, I, *V, F.getParent());
        ++Ref; break;
      case AliasAnalysis::ModRef:
        PrintModRefResults("  ModRef", PrintModRef, I, *V, F.getParent());
        ++ModRef; break;
      default:
        errs() << "Unknown alias query result!\n";
      }
    }
  }

  return false;
}

static void PrintPercent(unsigned Num, unsigned Sum) {
  errs() << "(" << Num*100ULL/Sum << "."
         << ((Num*1000ULL/Sum) % 10) << "%)\n";
}

bool AAEval::doFinalization(Module &M) {
  unsigned AliasSum = NoAlias + MayAlias + MustAlias;
  errs() << "===== Alias Analysis Evaluator Report =====\n";
  if (AliasSum == 0) {
    errs() << "  Alias Analysis Evaluator Summary: No pointers!\n";
  } else {
    errs() << "  " << AliasSum << " Total Alias Queries Performed\n";
    errs() << "  " << NoAlias << " no alias responses ";
    PrintPercent(NoAlias, AliasSum);
    errs() << "  " << MayAlias << " may alias responses ";
    PrintPercent(MayAlias, AliasSum);
    errs() << "  " << MustAlias << " must alias responses ";
    PrintPercent(MustAlias, AliasSum);
    errs() << "  Alias Analysis Evaluator Pointer Alias Summary: "
           << NoAlias*100/AliasSum  << "%/" << MayAlias*100/AliasSum << "%/"
           << MustAlias*100/AliasSum << "%\n";
  }

  // Display the summary for mod/ref analysis
  unsigned ModRefSum = NoModRef + Mod + Ref + ModRef;
  if (ModRefSum == 0) {
    errs() << "  Alias Analysis Mod/Ref Evaluator Summary: no mod/ref!\n";
  } else {
    errs() << "  " << ModRefSum << " Total ModRef Queries Performed\n";
    errs() << "  " << NoModRef << " no mod/ref responses ";
    PrintPercent(NoModRef, ModRefSum);
    errs() << "  " << Mod << " mod responses ";
    PrintPercent(Mod, ModRefSum);
    errs() << "  " << Ref << " ref responses ";
    PrintPercent(Ref, ModRefSum);
    errs() << "  " << ModRef << " mod & ref responses ";
    PrintPercent(ModRef, ModRefSum);
    errs() << "  Alias Analysis Evaluator Mod/Ref Summary: "
           << NoModRef*100/ModRefSum  << "%/" << Mod*100/ModRefSum << "%/"
           << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n";
  }

  return false;
}
<|endoftext|>


<commit_before>/* The MIT License (MIT)

Copyright (c) 2015 Gabriel Corona

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "unjit.hpp"

#include <sys/uio.h>

#include <stdexcept>
#include <iostream>
#include <iomanip>

#include <llvm-c/Target.h>
#include <llvm-c/Disassembler.h>

// This is an adapter for the API expected by LLVMDisasmContextRef:
static const char* lookup_symbol(
  void *DisInfo,
  uint64_t ReferenceValue,
  uint64_t *ReferenceType,
  uint64_t ReferencePC,
  const char **ReferenceName)
{
  unjit::Process *process = (unjit::Process *) DisInfo;
  *ReferenceType = 0;
  *ReferenceName = NULL;
  return process->lookup_symbol(ReferenceValue);
}

namespace unjit
{

Disassembler::Disassembler(Process& process) : process_(&process)
{
  // Create and setup the disassembler:
  this->disassembler_ = LLVMCreateDisasmCPU(
    LLVM_HOST_TRIPLE, "core2",
    this->process_, 0, NULL, lookup_symbol);
  if (!this->disassembler_) {
    throw std::runtime_error("Could not intialize LLVM disassembler");
  }
  LLVMSetDisasmOptions(this->disassembler_,
    LLVMDisassembler_Option_SetInstrComments
    | LLVMDisassembler_Option_PrintLatency
    );
}

Disassembler::~Disassembler()
{
  LLVMDisasmDispose(this->disassembler_);
}

void Disassembler::disassemble(std::ostream& stream, uint8_t *code, size_t size, uint64_t pc)
{
  char temp[256];
  while (size) {
    size_t c = LLVMDisasmInstruction(this->disassembler_,
      code, size, pc, temp, sizeof(temp));
    if (c == 0)
      return;
    stream << std::setfill('0') << std::setw(16) << std::hex << pc
      << " " << temp << '\n';
    size -= c;
    code += c;
    pc += c;
  }
}

void Disassembler::disassemble(std::ostream& stream, std::uint64_t start, std::uint64_t stop)
{
  Symbol symbol;
  symbol.size = stop - start;
  symbol.value = start;
  const char* name = process_->lookup_symbol(start);
  if (name)
    symbol.name = name;
  disassemble(stream, symbol);
}

void Disassembler::disassemble(std::ostream& stream, Symbol const& symbol)
{
  uint8_t buffer[symbol.size];
  struct iovec local, remote;

  local.iov_base = buffer;
  local.iov_len = symbol.size;

  remote.iov_base = (void*) symbol.value;
  remote.iov_len = symbol.size;

  if (process_vm_readv(this->process_->pid(), &local, 1, &remote, 1, 0) != symbol.size) {
    // TODO, return/throw error
    std::cerr << "Error, could not read the instructions for " << symbol.name << '\n';
    return;
  }

  stream << symbol.name << '\n';
  this->disassemble(stream, buffer, symbol.size, symbol.value);
  stream << '\n';
}

}
<commit_msg>Adjust output in order to be comptatible with perf<commit_after>/* The MIT License (MIT)

Copyright (c) 2015 Gabriel Corona

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "unjit.hpp"

#include <sys/uio.h>

#include <stdexcept>
#include <iostream>
#include <iomanip>

#include <llvm-c/Target.h>
#include <llvm-c/Disassembler.h>

// This is an adapter for the API expected by LLVMDisasmContextRef:
static const char* lookup_symbol(
  void *DisInfo,
  uint64_t ReferenceValue,
  uint64_t *ReferenceType,
  uint64_t ReferencePC,
  const char **ReferenceName)
{
  unjit::Process *process = (unjit::Process *) DisInfo;
  *ReferenceType = 0;
  *ReferenceName = NULL;
  return process->lookup_symbol(ReferenceValue);
}

namespace unjit
{

Disassembler::Disassembler(Process& process) : process_(&process)
{
  // Create and setup the disassembler:
  this->disassembler_ = LLVMCreateDisasmCPU(
    LLVM_HOST_TRIPLE, "core2",
    this->process_, 0, NULL, lookup_symbol);
  if (!this->disassembler_) {
    throw std::runtime_error("Could not intialize LLVM disassembler");
  }
  LLVMSetDisasmOptions(this->disassembler_,
    LLVMDisassembler_Option_SetInstrComments
    | LLVMDisassembler_Option_PrintLatency
    );
}

Disassembler::~Disassembler()
{
  LLVMDisasmDispose(this->disassembler_);
}

void Disassembler::disassemble(std::ostream& stream, uint8_t *code, size_t size, uint64_t pc)
{
  char temp[256];
  while (size) {
    size_t c = LLVMDisasmInstruction(this->disassembler_,
      code, size, pc, temp, sizeof(temp));
    if (c == 0)
      return;
    stream << std::setfill('0') << std::setw(16) << std::hex << pc
      << ":\t" << temp << '\n';
    size -= c;
    code += c;
    pc += c;
  }
}

void Disassembler::disassemble(std::ostream& stream, std::uint64_t start, std::uint64_t stop)
{
  Symbol symbol;
  symbol.size = stop - start;
  symbol.value = start;
  const char* name = process_->lookup_symbol(start);
  if (name)
    symbol.name = name;
  disassemble(stream, symbol);
}

void Disassembler::disassemble(std::ostream& stream, Symbol const& symbol)
{
  uint8_t buffer[symbol.size];
  struct iovec local, remote;

  local.iov_base = buffer;
  local.iov_len = symbol.size;

  remote.iov_base = (void*) symbol.value;
  remote.iov_len = symbol.size;

  if (process_vm_readv(this->process_->pid(), &local, 1, &remote, 1, 0) != symbol.size) {
    // TODO, return/throw error
    std::cerr << "Error, could not read the instructions for " << symbol.name << '\n';
    return;
  }

  stream << std::hex << symbol.value << '<' << symbol.name << ">\n";
  this->disassemble(stream, buffer, symbol.size, symbol.value);
  stream << '\n';
}

}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalExecutor.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace llvm;
namespace cling {

std::set<std::string> IncrementalExecutor::m_unresolvedSymbols;
std::vector<IncrementalExecutor::LazyFunctionCreatorFunc_t>
  IncrementalExecutor::m_lazyFuncCreator;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
IncrementalExecutor::IncrementalExecutor(llvm::Module* m)
  : m_CxaAtExitRemapped(false) {
  assert(m && "llvm::Module must not be null!");
  m_AtExitFuncs.reserve(256);

  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::IncrementalExecutor::IncrementalExecutor(): "
                  << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
IncrementalExecutor::~IncrementalExecutor() {}

void IncrementalExecutor::shuttingDown() {
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void IncrementalExecutor::remapCXAAtExit() {
  if (m_CxaAtExitRemapped)
    return;

  llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
  if (!atExit)
    return;

  llvm::Function* clingAtExit
    = m_engine->FindFunctionNamed("cling_cxa_atexit");
  assert(clingAtExit && "cling_cxa_atexit must exist.");

  void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
  assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
  m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
  m_CxaAtExitRemapped = true;
}

void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg,
                                        const cling::Transaction* T) {
  // Register a CXAAtExit function
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, T));
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "IncrementalExecutor: calling unresolved symbol, "
    "see previous error message!\n";
}

void* IncrementalExecutor::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "IncrementalExecutor: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
IncrementalExecutor::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

IncrementalExecutor::ExecutionResult
IncrementalExecutor::executeFunction(llvm::StringRef funcname,
                                     StoredValueRef* returnValue) {
  // Call a function without arguments, or with an SRet argument, see SRet below
  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  remapCXAAtExit();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "IncrementalExecutor::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  assert (f->getFunctionType()->getNumParams() == 1
          && (*f->getFunctionType()->param_begin())->isPtrOrPtrVectorTy() &&
          "Wrong signature");
  typedef void (*PromptWrapper_t)(void*);
  union {
    PromptWrapper_t wrapperFunction;
    void* address;
  } p2f;
  p2f.address = m_engine->getPointerToFunction(f);

  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 128> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      // i could also reference a global variable, in which case ff == 0.
      if (ff)
        funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  // Run the function
  (*p2f.wrapperFunction)(returnValue);

  return kExeSuccess;
}

IncrementalExecutor::ExecutionResult
IncrementalExecutor::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());

  GV->eraseFromParent();

  if (InitList == 0)
    return kExeSuccess;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  SmallVector<Function*, 2> initFuncs;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      remapCXAAtExit();
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "IncrementalExecutor::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        return kExeUnresolvedSymbols;
      }
      //executeFunction(F->getName());
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
      initFuncs.push_back(F);
    }
  }

  for (SmallVector<Function*,2>::iterator I = initFuncs.begin(),
         E = initFuncs.end(); I != E; ++I) {
    // Cleanup also the dangling init functions. They are in the form:
    // define internal void @_GLOBAL__I_aN() section "..."{
    // entry:
    //   call void @__cxx_global_var_init(N-1)()
    //   ret void
    // }
    //
    // define internal void @__cxx_global_var_init(N-1)() section "..." {
    // entry:
    //   call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
    //   ret void
    // }

    // Erase __cxx_global_var_init(N-1)() first.
    Function* GlobalVarInitF =
      cast<Function>((*I)->getEntryBlock().getFirstNonPHI()->getOperand(0));
    (*I)->eraseFromParent();
    GlobalVarInitF->eraseFromParent();
  }

  return kExeSuccess;
}

void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
  assert(T && "Must be set");
  // Collect all the dtors bound to this transaction.
  AtExitFunctions boundToT;
  for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
       I != m_AtExitFuncs.end();)
    if (I->m_FromT == T) {
      boundToT.push_back(*I);
      I = m_AtExitFuncs.erase(I);
    }
    else
      ++I;

  // 'Unload' the cxa_atexit entities.
  for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),
         E = boundToT.rend(); I != E; ++I) {
    const CXAAtExitElement& AEE = *I;
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void
IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool
IncrementalExecutor::addSymbol(const char* symbolName,  void* symbolAddress) {
  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::Module* m,
                                              llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    remapCXAAtExit();
    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}

void*
IncrementalExecutor::getPointerToGlobalFromJIT(const llvm::GlobalValue& GV) {
  remapCXAAtExit();
  if (void* addr = m_engine->getPointerToGlobalIfAvailable(&GV))
    return addr;

  //  Function not yet codegened by the JIT, force this to happen now.
  return m_engine->getPointerToGlobal(&GV);
}
}// end namespace cling
<commit_msg>Add clarification comment.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalExecutor.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace llvm;
namespace cling {

std::set<std::string> IncrementalExecutor::m_unresolvedSymbols;
std::vector<IncrementalExecutor::LazyFunctionCreatorFunc_t>
  IncrementalExecutor::m_lazyFuncCreator;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
IncrementalExecutor::IncrementalExecutor(llvm::Module* m)
  : m_CxaAtExitRemapped(false) {
  assert(m && "llvm::Module must not be null!");
  m_AtExitFuncs.reserve(256);

  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::IncrementalExecutor::IncrementalExecutor(): "
                  << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
IncrementalExecutor::~IncrementalExecutor() {}

void IncrementalExecutor::shuttingDown() {
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void IncrementalExecutor::remapCXAAtExit() {
  if (m_CxaAtExitRemapped)
    return;

  llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
  if (!atExit)
    return;

  llvm::Function* clingAtExit
    = m_engine->FindFunctionNamed("cling_cxa_atexit");
  assert(clingAtExit && "cling_cxa_atexit must exist.");

  void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
  assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
  m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
  m_CxaAtExitRemapped = true;
}

void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg,
                                        const cling::Transaction* T) {
  // Register a CXAAtExit function
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, T));
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "IncrementalExecutor: calling unresolved symbol, "
    "see previous error message!\n";
}

void* IncrementalExecutor::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "IncrementalExecutor: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
IncrementalExecutor::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

IncrementalExecutor::ExecutionResult
IncrementalExecutor::executeFunction(llvm::StringRef funcname,
                                     StoredValueRef* returnValue) {
  // Call a function without arguments, or with an SRet argument, see SRet below
  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  remapCXAAtExit();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "IncrementalExecutor::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  assert (f->getFunctionType()->getNumParams() == 1
          && (*f->getFunctionType()->param_begin())->isPtrOrPtrVectorTy() &&
          "Wrong signature");
  typedef void (*PromptWrapper_t)(void*);
  union {
    PromptWrapper_t wrapperFunction;
    void* address;
  } p2f;
  p2f.address = m_engine->getPointerToFunction(f);

  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 128> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      // i could also reference a global variable, in which case ff == 0.
      if (ff)
        funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  // Run the function
  (*p2f.wrapperFunction)(returnValue);

  return kExeSuccess;
}

IncrementalExecutor::ExecutionResult
IncrementalExecutor::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());

  // We need to delete it here just in case we have recursive inits, otherwise
  // it will call inits multiple times.
  GV->eraseFromParent();

  if (InitList == 0)
    return kExeSuccess;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  SmallVector<Function*, 2> initFuncs;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      remapCXAAtExit();
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "IncrementalExecutor::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        return kExeUnresolvedSymbols;
      }
      //executeFunction(F->getName());
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
      initFuncs.push_back(F);
    }
  }

  for (SmallVector<Function*,2>::iterator I = initFuncs.begin(),
         E = initFuncs.end(); I != E; ++I) {
    // Cleanup also the dangling init functions. They are in the form:
    // define internal void @_GLOBAL__I_aN() section "..."{
    // entry:
    //   call void @__cxx_global_var_init(N-1)()
    //   ret void
    // }
    //
    // define internal void @__cxx_global_var_init(N-1)() section "..." {
    // entry:
    //   call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
    //   ret void
    // }

    // Erase __cxx_global_var_init(N-1)() first.
    Function* GlobalVarInitF =
      cast<Function>((*I)->getEntryBlock().getFirstNonPHI()->getOperand(0));
    (*I)->eraseFromParent();
    GlobalVarInitF->eraseFromParent();
  }

  return kExeSuccess;
}

void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
  assert(T && "Must be set");
  // Collect all the dtors bound to this transaction.
  AtExitFunctions boundToT;
  for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
       I != m_AtExitFuncs.end();)
    if (I->m_FromT == T) {
      boundToT.push_back(*I);
      I = m_AtExitFuncs.erase(I);
    }
    else
      ++I;

  // 'Unload' the cxa_atexit entities.
  for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),
         E = boundToT.rend(); I != E; ++I) {
    const CXAAtExitElement& AEE = *I;
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void
IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool
IncrementalExecutor::addSymbol(const char* symbolName,  void* symbolAddress) {
  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::Module* m,
                                              llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    remapCXAAtExit();
    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}

void*
IncrementalExecutor::getPointerToGlobalFromJIT(const llvm::GlobalValue& GV) {
  remapCXAAtExit();
  if (void* addr = m_engine->getPointerToGlobalIfAvailable(&GV))
    return addr;

  //  Function not yet codegened by the JIT, force this to happen now.
  return m_engine->getPointerToGlobal(&GV);
}
}// end namespace cling
<|endoftext|>