<commit_before>//== MemRegion.cpp - Abstract memory regions for static analysis --*- C++ -*--//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines MemRegion and its subclasses.  MemRegion defines a
//  partially-typed abstraction of memory useful for path-sensitive dataflow
//  analyses.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/raw_ostream.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Basic methods.
//===----------------------------------------------------------------------===//

MemRegion::~MemRegion() {}

bool SubRegion::isSubRegionOf(const MemRegion* R) const {
  const MemRegion* r = getSuperRegion();
  while (r != 0) {
    if (r == R)
      return true;
    if (const SubRegion* sr = dyn_cast<SubRegion>(r))
      r = sr->getSuperRegion();
    else
      break;
  }
  return false;
}

void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  ID.AddInteger((unsigned)getKind());
}

void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                 const StringLiteral* Str,
                                 const MemRegion* superRegion) {
  ID.AddInteger((unsigned) StringRegionKind);
  ID.AddPointer(Str);
  ID.AddPointer(superRegion);
}

void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                 const Expr* Ex, unsigned cnt) {
  ID.AddInteger((unsigned) AllocaRegionKind);
  ID.AddPointer(Ex);
  ID.AddInteger(cnt);
}

void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  ProfileRegion(ID, Ex, Cnt);
}

void TypedViewRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
                                    const MemRegion* superRegion) {
  ID.AddInteger((unsigned) TypedViewRegionKind);
  ID.Add(T);
  ID.AddPointer(superRegion);
}

void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
}

void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                          const CompoundLiteralExpr* CL,
                                          const MemRegion* superRegion) {
  ID.AddInteger((unsigned) CompoundLiteralRegionKind);
  ID.AddPointer(CL);
  ID.AddPointer(superRegion);
}

void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
                               const MemRegion* superRegion, Kind k) {
  ID.AddInteger((unsigned) k);
  ID.AddPointer(D);
  ID.AddPointer(superRegion);
}

void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
}

void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
                                   const MemRegion *sreg) {
  ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
  ID.Add(sym);
  ID.AddPointer(sreg);
}

void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
}

void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                  QualType ElementType, SVal Idx,
                                  const MemRegion* superRegion) {
  ID.AddInteger(MemRegion::ElementRegionKind);
  ID.Add(ElementType);
  ID.AddPointer(superRegion);
  Idx.Profile(ID);
}

void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
}

void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const void* data,
                                   QualType t) {
  ID.AddInteger(MemRegion::CodeTextRegionKind);
  ID.AddPointer(data);
  ID.Add(t);
}

void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  CodeTextRegion::ProfileRegion(ID, Data, LocationType);
}

//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//

std::string MemRegion::getString() const {
  std::string s;
  llvm::raw_string_ostream os(s);
  print(os);
  return os.str();
}

void MemRegion::print(llvm::raw_ostream& os) const {
  os << "<Unknown Region>";
}

void AllocaRegion::print(llvm::raw_ostream& os) const {
  os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
}

void CodeTextRegion::print(llvm::raw_ostream& os) const {
  os << "code{";
  if (isDeclared())
    os << getDecl()->getDeclName().getAsString();
  else
    os << '$' << getSymbol();

  os << '}';
}

void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
  // FIXME: More elaborate pretty-printing.
  os << "{ " << (void*) CL <<  " }";
}

void ElementRegion::print(llvm::raw_ostream& os) const {
  superRegion->print(os);
  os << '['; Index.print(os); os << ']';
}

void FieldRegion::print(llvm::raw_ostream& os) const {
  superRegion->print(os);
  os << "->" << getDecl()->getNameAsString();
}

void StringRegion::print(llvm::raw_ostream& os) const {
  Str->printPretty(os);
}

void SymbolicRegion::print(llvm::raw_ostream& os) const {
  os << "SymRegion-" << sym;
}

void TypedViewRegion::print(llvm::raw_ostream& os) const {
  os << "typed_view{" << LValueType.getAsString() << ',';
  getSuperRegion()->print(os);
  os << '}';
}

void VarRegion::print(llvm::raw_ostream& os) const {
  os << cast<VarDecl>(D)->getNameAsString();
}

//===----------------------------------------------------------------------===//
// MemRegionManager methods.
//===----------------------------------------------------------------------===//

MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {

  if (!region) {
    region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
    new (region) MemSpaceRegion();
  }

  return region;
}

MemSpaceRegion* MemRegionManager::getStackRegion() {
  return LazyAllocate(stack);
}

MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
  return LazyAllocate(globals);
}

MemSpaceRegion* MemRegionManager::getHeapRegion() {
  return LazyAllocate(heap);
}

MemSpaceRegion* MemRegionManager::getUnknownRegion() {
  return LazyAllocate(unknown);
}

MemSpaceRegion* MemRegionManager::getCodeRegion() {
  return LazyAllocate(code);
}

bool MemRegionManager::onStack(const MemRegion* R) {
  while (const SubRegion* SR = dyn_cast<SubRegion>(R))
    R = SR->getSuperRegion();

  return (R != 0) && (R == stack);
}

bool MemRegionManager::onHeap(const MemRegion* R) {
  while (const SubRegion* SR = dyn_cast<SubRegion>(R))
    R = SR->getSuperRegion();

  return (R != 0) && (R == heap);
}

//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//

StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
  return getRegion<StringRegion>(Str);
}

VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
  return getRegion<VarRegion>(d);
}

CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
  return getRegion<CompoundLiteralRegion>(CL);
}

ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
                                 const MemRegion* superRegion, ASTContext& Ctx){

  QualType T = Ctx.getCanonicalType(elementType);

  llvm::FoldingSetNodeID ID;
  ElementRegion::ProfileRegion(ID, T, Idx, superRegion);

  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  ElementRegion* R = cast_or_null<ElementRegion>(data);

  if (!R) {
    R = (ElementRegion*) A.Allocate<ElementRegion>();
    new (R) ElementRegion(T, Idx, superRegion);
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

CodeTextRegion* MemRegionManager::getCodeTextRegion(const FunctionDecl* fd,
                                                    QualType t) {
  llvm::FoldingSetNodeID ID;
  CodeTextRegion::ProfileRegion(ID, fd, t);
  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);

  if (!R) {
    R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
    new (R) CodeTextRegion(fd, t, getCodeRegion());
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

CodeTextRegion* MemRegionManager::getCodeTextRegion(SymbolRef sym, QualType t) {
  llvm::FoldingSetNodeID ID;
  CodeTextRegion::ProfileRegion(ID, sym, t);
  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);

  if (!R) {
    R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
    new (R) CodeTextRegion(sym, t, getCodeRegion());
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
  return getRegion<SymbolicRegion>(sym);
}

FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
                                              const MemRegion* superRegion) {
  return getRegion<FieldRegion>(d, superRegion);
}

ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
                                    const MemRegion* superRegion) {
  return getRegion<ObjCIvarRegion>(d, superRegion);
}

ObjCObjectRegion*
MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
                                    const MemRegion* superRegion) {
  llvm::FoldingSetNodeID ID;
  DeclRegion::ProfileRegion(ID, d, superRegion,
                            MemRegion::ObjCObjectRegionKind);

  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);

  if (!R) {
    R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
    new (R) ObjCObjectRegion(d, superRegion);
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

TypedViewRegion*
MemRegionManager::getTypedViewRegion(QualType t, const MemRegion* superRegion) {
  llvm::FoldingSetNodeID ID;
  TypedViewRegion::ProfileRegion(ID, t, superRegion);

  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  TypedViewRegion* R = cast_or_null<TypedViewRegion>(data);

  if (!R) {
    R = (TypedViewRegion*) A.Allocate<TypedViewRegion>();
    new (R) TypedViewRegion(t, superRegion);
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
  llvm::FoldingSetNodeID ID;
  AllocaRegion::ProfileRegion(ID, E, cnt);

  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  AllocaRegion* R = cast_or_null<AllocaRegion>(data);

  if (!R) {
    R = (AllocaRegion*) A.Allocate<AllocaRegion>();
    new (R) AllocaRegion(E, cnt, getStackRegion());
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

bool MemRegionManager::hasStackStorage(const MemRegion* R) {

  // Only subregions can have stack storage.
  const SubRegion* SR = dyn_cast<SubRegion>(R);

  if (!SR)
    return false;

  MemSpaceRegion* S = getStackRegion();

  while (SR) {
    R = SR->getSuperRegion();
    if (R == S)
      return true;

    SR = dyn_cast<SubRegion>(R);
  }

  return false;
}

//===----------------------------------------------------------------------===//
// View handling.
//===----------------------------------------------------------------------===//

const MemRegion *TypedViewRegion::removeViews() const {
  const SubRegion *SR = this;
  const MemRegion *R = SR;
  while (SR && isa<TypedViewRegion>(SR)) {
    R = SR->getSuperRegion();
    SR = dyn_cast<SubRegion>(R);
  }
  return R;
}
<commit_msg>MemRegionManager: Migrate getObjCObjectRegion() and getTypedViewRegion() to use the new trait-based construction of MemRegion objects.<commit_after>//== MemRegion.cpp - Abstract memory regions for static analysis --*- C++ -*--//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines MemRegion and its subclasses.  MemRegion defines a
//  partially-typed abstraction of memory useful for path-sensitive dataflow
//  analyses.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/raw_ostream.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"

using namespace clang;

//===----------------------------------------------------------------------===//
// Basic methods.
//===----------------------------------------------------------------------===//

MemRegion::~MemRegion() {}

bool SubRegion::isSubRegionOf(const MemRegion* R) const {
  const MemRegion* r = getSuperRegion();
  while (r != 0) {
    if (r == R)
      return true;
    if (const SubRegion* sr = dyn_cast<SubRegion>(r))
      r = sr->getSuperRegion();
    else
      break;
  }
  return false;
}

void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  ID.AddInteger((unsigned)getKind());
}

void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                 const StringLiteral* Str,
                                 const MemRegion* superRegion) {
  ID.AddInteger((unsigned) StringRegionKind);
  ID.AddPointer(Str);
  ID.AddPointer(superRegion);
}

void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                 const Expr* Ex, unsigned cnt) {
  ID.AddInteger((unsigned) AllocaRegionKind);
  ID.AddPointer(Ex);
  ID.AddInteger(cnt);
}

void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  ProfileRegion(ID, Ex, Cnt);
}

void TypedViewRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
                                    const MemRegion* superRegion) {
  ID.AddInteger((unsigned) TypedViewRegionKind);
  ID.Add(T);
  ID.AddPointer(superRegion);
}

void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
}

void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                          const CompoundLiteralExpr* CL,
                                          const MemRegion* superRegion) {
  ID.AddInteger((unsigned) CompoundLiteralRegionKind);
  ID.AddPointer(CL);
  ID.AddPointer(superRegion);
}

void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
                               const MemRegion* superRegion, Kind k) {
  ID.AddInteger((unsigned) k);
  ID.AddPointer(D);
  ID.AddPointer(superRegion);
}

void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
}

void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
                                   const MemRegion *sreg) {
  ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
  ID.Add(sym);
  ID.AddPointer(sreg);
}

void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
}

void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                  QualType ElementType, SVal Idx,
                                  const MemRegion* superRegion) {
  ID.AddInteger(MemRegion::ElementRegionKind);
  ID.Add(ElementType);
  ID.AddPointer(superRegion);
  Idx.Profile(ID);
}

void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
}

void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const void* data,
                                   QualType t) {
  ID.AddInteger(MemRegion::CodeTextRegionKind);
  ID.AddPointer(data);
  ID.Add(t);
}

void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
  CodeTextRegion::ProfileRegion(ID, Data, LocationType);
}

//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//

std::string MemRegion::getString() const {
  std::string s;
  llvm::raw_string_ostream os(s);
  print(os);
  return os.str();
}

void MemRegion::print(llvm::raw_ostream& os) const {
  os << "<Unknown Region>";
}

void AllocaRegion::print(llvm::raw_ostream& os) const {
  os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
}

void CodeTextRegion::print(llvm::raw_ostream& os) const {
  os << "code{";
  if (isDeclared())
    os << getDecl()->getDeclName().getAsString();
  else
    os << '$' << getSymbol();

  os << '}';
}

void CompoundLiteralRegion::print(llvm::raw_ostream& os) const {
  // FIXME: More elaborate pretty-printing.
  os << "{ " << (void*) CL <<  " }";
}

void ElementRegion::print(llvm::raw_ostream& os) const {
  superRegion->print(os);
  os << '['; Index.print(os); os << ']';
}

void FieldRegion::print(llvm::raw_ostream& os) const {
  superRegion->print(os);
  os << "->" << getDecl()->getNameAsString();
}

void StringRegion::print(llvm::raw_ostream& os) const {
  Str->printPretty(os);
}

void SymbolicRegion::print(llvm::raw_ostream& os) const {
  os << "SymRegion-" << sym;
}

void TypedViewRegion::print(llvm::raw_ostream& os) const {
  os << "typed_view{" << LValueType.getAsString() << ',';
  getSuperRegion()->print(os);
  os << '}';
}

void VarRegion::print(llvm::raw_ostream& os) const {
  os << cast<VarDecl>(D)->getNameAsString();
}

//===----------------------------------------------------------------------===//
// MemRegionManager methods.
//===----------------------------------------------------------------------===//

MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {

  if (!region) {
    region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
    new (region) MemSpaceRegion();
  }

  return region;
}

MemSpaceRegion* MemRegionManager::getStackRegion() {
  return LazyAllocate(stack);
}

MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
  return LazyAllocate(globals);
}

MemSpaceRegion* MemRegionManager::getHeapRegion() {
  return LazyAllocate(heap);
}

MemSpaceRegion* MemRegionManager::getUnknownRegion() {
  return LazyAllocate(unknown);
}

MemSpaceRegion* MemRegionManager::getCodeRegion() {
  return LazyAllocate(code);
}

bool MemRegionManager::onStack(const MemRegion* R) {
  while (const SubRegion* SR = dyn_cast<SubRegion>(R))
    R = SR->getSuperRegion();

  return (R != 0) && (R == stack);
}

bool MemRegionManager::onHeap(const MemRegion* R) {
  while (const SubRegion* SR = dyn_cast<SubRegion>(R))
    R = SR->getSuperRegion();

  return (R != 0) && (R == heap);
}

//===----------------------------------------------------------------------===//
// Constructing regions.
//===----------------------------------------------------------------------===//

StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
  return getRegion<StringRegion>(Str);
}

VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
  return getRegion<VarRegion>(d);
}

CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
  return getRegion<CompoundLiteralRegion>(CL);
}

ElementRegion*
MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
                                 const MemRegion* superRegion, ASTContext& Ctx){

  QualType T = Ctx.getCanonicalType(elementType);

  llvm::FoldingSetNodeID ID;
  ElementRegion::ProfileRegion(ID, T, Idx, superRegion);

  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  ElementRegion* R = cast_or_null<ElementRegion>(data);

  if (!R) {
    R = (ElementRegion*) A.Allocate<ElementRegion>();
    new (R) ElementRegion(T, Idx, superRegion);
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

CodeTextRegion* MemRegionManager::getCodeTextRegion(const FunctionDecl* fd,
                                                    QualType t) {
  llvm::FoldingSetNodeID ID;
  CodeTextRegion::ProfileRegion(ID, fd, t);
  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);

  if (!R) {
    R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
    new (R) CodeTextRegion(fd, t, getCodeRegion());
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

CodeTextRegion* MemRegionManager::getCodeTextRegion(SymbolRef sym, QualType t) {
  llvm::FoldingSetNodeID ID;
  CodeTextRegion::ProfileRegion(ID, sym, t);
  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);

  if (!R) {
    R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
    new (R) CodeTextRegion(sym, t, getCodeRegion());
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
  return getRegion<SymbolicRegion>(sym);
}

FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
                                              const MemRegion* superRegion) {
  return getRegion<FieldRegion>(d, superRegion);
}

ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
                                    const MemRegion* superRegion) {
  return getRegion<ObjCIvarRegion>(d, superRegion);
}

ObjCObjectRegion*
MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
                                      const MemRegion* superRegion) {
  return getRegion<ObjCObjectRegion>(d, superRegion);
}

TypedViewRegion*
MemRegionManager::getTypedViewRegion(QualType t, const MemRegion* superRegion) {
  return getRegion<TypedViewRegion>(t, superRegion);
}

AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
  llvm::FoldingSetNodeID ID;
  AllocaRegion::ProfileRegion(ID, E, cnt);

  void* InsertPos;
  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
  AllocaRegion* R = cast_or_null<AllocaRegion>(data);

  if (!R) {
    R = (AllocaRegion*) A.Allocate<AllocaRegion>();
    new (R) AllocaRegion(E, cnt, getStackRegion());
    Regions.InsertNode(R, InsertPos);
  }

  return R;
}

bool MemRegionManager::hasStackStorage(const MemRegion* R) {

  // Only subregions can have stack storage.
  const SubRegion* SR = dyn_cast<SubRegion>(R);

  if (!SR)
    return false;

  MemSpaceRegion* S = getStackRegion();

  while (SR) {
    R = SR->getSuperRegion();
    if (R == S)
      return true;

    SR = dyn_cast<SubRegion>(R);
  }

  return false;
}

//===----------------------------------------------------------------------===//
// View handling.
//===----------------------------------------------------------------------===//

const MemRegion *TypedViewRegion::removeViews() const {
  const SubRegion *SR = this;
  const MemRegion *R = SR;
  while (SR && isa<TypedViewRegion>(SR)) {
    R = SR->getSuperRegion();
    SR = dyn_cast<SubRegion>(R);
  }
  return R;
}
<|endoftext|>


<commit_before>/* Ticker library code is placed under the MIT license
 * Copyright (c) 2018 Stefan Staub
 *
 * 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 "Ticker.h"

Ticker::Ticker(fptr callback, uint32_t timer, uint32_t repeat, resolution_t resolution) {
	this->resolution = resolution;
	if (resolution == MICROS) timer = timer * 1000;
	this->timer = timer;
	this->repeat = repeat;
	this->callback = callback;
	enabled = false;
	lastTime = 0;
	counts = 0;
	}

Ticker::~Ticker() {}

void Ticker::start() {
	if (callback == NULL) return;
	if (resolution == MILLIS) lastTime = millis();
	else lastTime = micros();
	enabled = true;
	counts = 0;
	status = RUNNING;
	}

void Ticker::resume() {
	if (callback == NULL) return;
	if (resolution == MILLIS) lastTime = millis() - diffTime;
	else lastTime = micros() - diffTime;
	if (status == STOPPED) counts = 0;
	enabled = true;
	status = RUNNING;
	}

void Ticker::stop() {
	enabled = false;
	counts = 0;
	status = STOPPED;
	}

void Ticker::pause() {
	if (resolution == MILLIS) diffTime = millis() - lastTime;
	else diffTime = micros() - lastTime;
	enabled = false;
	status = PAUSED;
	}

void Ticker::update() {
	if (tick()) callback();
	}

bool Ticker::tick() {
	if (!enabled)	return false;
	uint32_t currentTime = (resolution == MILLIS) ? millis() : micros();
 	if ((currentTime - lastTime) >= timer) {
 		lastTime = currentTime;
 		if (repeat - counts == 1 && counts != 0xFFFFFFFF) enabled = false;
		counts++;
 		return true;
 		}
	return false;
	}

void Ticker::interval(uint32_t timer) {
	if (resolution == MICROS) timer *= 1000;
	this->timer = timer;
	}

uint32_t Ticker::interval() {
	if (resolution == MILLIS) return timer / 1000;
	else return timer;
	}

uint32_t Ticker::elapsed() {
	if (resolution == MILLIS) return millis() - lastTime;
	else return micros() - lastTime;
	}

uint32_t Ticker::remaining() {
	if (resolution == MILLIS) {
		return timer / 1000 - elapsed();
		}
	else return timer - elapsed();
	}

status_t Ticker::state() {
	return status;
	}

uint32_t Ticker::counter() {
	return counts;
	}
<commit_msg>Update Ticker.cpp<commit_after>/* Ticker library code is placed under the MIT license
 * Copyright (c) 2018 Stefan Staub
 *
 * 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 "Ticker.h"

Ticker::Ticker(fptr callback, uint32_t timer, uint32_t repeat, resolution_t resolution) {
	this->resolution = resolution;
	if (resolution == MICROS) timer = timer * 1000;
	this->timer = timer;
	this->repeat = repeat;
	this->callback = callback;
	enabled = false;
	lastTime = 0;
	counts = 0;
	}

Ticker::~Ticker() {}

void Ticker::start() {
	if (callback == NULL) return;
	if (resolution == MILLIS) lastTime = millis();
	else lastTime = micros();
	enabled = true;
	counts = 0;
	status = RUNNING;
	}

void Ticker::resume() {
	if (callback == NULL) return;
	if (resolution == MILLIS) lastTime = millis() - diffTime;
	else lastTime = micros() - diffTime;
	if (status == STOPPED) counts = 0;
	enabled = true;
	status = RUNNING;
	}

void Ticker::stop() {
	enabled = false;
	counts = 0;
	status = STOPPED;
	}

void Ticker::pause() {
	if (resolution == MILLIS) diffTime = millis() - lastTime;
	else diffTime = micros() - lastTime;
	enabled = false;
	status = PAUSED;
	}

void Ticker::update() {
	if (tick()) callback();
	}

bool Ticker::tick() {
	if (!enabled)	return false;
	uint32_t currentTime = (resolution == MILLIS) ? millis() : micros();
 	if ((currentTime - lastTime) >= timer) {
 		lastTime = currentTime;
 		if (repeat - counts == 1 && counts != 0xFFFFFFFF) {
			enabled = false;
			status = STOPPED;
		}
		counts++;
 		return true;
 		}
	return false;
	}

void Ticker::interval(uint32_t timer) {
	if (resolution == MICROS) timer *= 1000;
	this->timer = timer;
	}

uint32_t Ticker::interval() {
	if (resolution == MILLIS) return timer / 1000;
	else return timer;
	}

uint32_t Ticker::elapsed() {
	if (resolution == MILLIS) return millis() - lastTime;
	else return micros() - lastTime;
	}

uint32_t Ticker::remaining() {
	if (resolution == MILLIS) {
		return timer / 1000 - elapsed();
		}
	else return timer - elapsed();
	}

status_t Ticker::state() {
	return status;
	}

uint32_t Ticker::counter() {
	return counts;
	}
<|endoftext|>


<commit_before>#ifndef TOPOLOGICALMESH_H
#define TOPOLOGICALMESH_H

#include <Core/Index/Index.hpp>
#include <Core/Math/LinearAlgebra.hpp>
#include <Core/RaCore.hpp>

#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Utils/Property.hh>

namespace Ra {
namespace Core {

///\class TopoVector3 : small extension to Vector3 for OpenMesh compatibility
class TopoVector3 : public Ra::Core::Vector3 {
  public:
    using Ra::Core::Vector3::Vector3;
    inline Scalar length() const { return norm(); }
    inline Scalar sqrnorm() const { return squaredNorm(); }
    inline TopoVector3 vectorize( Scalar v ) {
        ( *this )[0] = v;
        ( *this )[1] = v;
        ( *this )[2] = v;
        return *this;
    }
    inline TopoVector3 normalize() {
        Ra::Core::Vector3::normalize();
        return *this;
    }
};

inline Scalar dot( const TopoVector3& a, const TopoVector3& b ) {
    return a.dot( b );
}
inline TopoVector3 cross( const TopoVector3& a, const TopoVector3& b ) {
    return a.cross( b );
}
} // namespace Core
} // namespace Ra

template <>
struct OpenMesh::vector_traits<Ra::Core::TopoVector3> {
    /// Type of the vector class
    typedef typename Ra::Core::Vector3 vector_type;

    /// Type of the scalar value
    typedef Scalar value_type;

    /// size/dimension of the vector
    static const size_t size_ = 3;

    /// size/dimension of the vector
    static inline size_t size() { return size_; }
};

namespace Ra {
namespace Core {

// Define an OpenMesh TriMesh structure according to
// http://openmesh.org/Documentation/OpenMesh-2.1-Documentation/mesh_type.html
// Attributes define data store on structure.

struct TopologicalMeshTraits : public OpenMesh::DefaultTraits {
    typedef TopoVector3 Point;
    typedef TopoVector3 Normal;

    VertexAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
    FaceAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
    EdgeAttributes( OpenMesh::Attributes::Status );
    HalfedgeAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );

    VertexTraits {
      private:
        Index m_index;

      public:
        /// If index valid, normal is TriMesh vertex normal
        inline Index getIndex() { return m_index; }
        inline void setIndex( Index index ) { m_index = index; }
    };

    HalfedgeTraits {
      private:
        Index m_index;

      public:
        /// if Index valid, normal and other data of halfedge is TriMesh vertex data
        inline Index getIndex() { return m_index; }
        inline void setIndex( Index index ) { m_index = index; }
    };

  public:
};

class TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT<TopologicalMeshTraits> {
    using base = OpenMesh::PolyMesh_ArrayKernelT<TopologicalMeshTraits>;
    using base::PolyMesh_ArrayKernelT;

  public:
    inline Normal& normal( VertexHandle vh, FaceHandle fh ) {
        // find halfedge that point to vh and member of fh
        return property( halfedge_normals_pph(), halfedge_handle( vh, fh ) );
    }

    using base::halfedge_handle;
    inline HalfedgeHandle halfedge_handle( VertexHandle vh, FaceHandle fh ) {

        for ( VertexIHalfedgeIter vih_it = vih_iter( vh ); vih_it.is_valid(); ++vih_it )
        {
            if ( face_handle( *vih_it ) == fh )
            {
                return *vih_it;
            }
        }
        return HalfedgeHandle();
    }
};
} // namespace Core
} // namespace Ra

#endif // TOPOLOGICALMESH_H
<commit_msg>Switch back to using instead of typedef.<commit_after>#ifndef TOPOLOGICALMESH_H
#define TOPOLOGICALMESH_H

#include <Core/Index/Index.hpp>
#include <Core/Math/LinearAlgebra.hpp>
#include <Core/RaCore.hpp>

#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Utils/Property.hh>

namespace Ra {
namespace Core {

///\class TopoVector3 : small extension to Vector3 for OpenMesh compatibility
class TopoVector3 : public Ra::Core::Vector3 {
  public:
    using Ra::Core::Vector3::Vector3;
    inline Scalar length() const { return norm(); }
    inline Scalar sqrnorm() const { return squaredNorm(); }
    inline TopoVector3 vectorize( Scalar v ) {
        ( *this )[0] = v;
        ( *this )[1] = v;
        ( *this )[2] = v;
        return *this;
    }
    inline TopoVector3 normalize() {
        Ra::Core::Vector3::normalize();
        return *this;
    }
};

inline Scalar dot( const TopoVector3& a, const TopoVector3& b ) {
    return a.dot( b );
}
inline TopoVector3 cross( const TopoVector3& a, const TopoVector3& b ) {
    return a.cross( b );
}
} // namespace Core
} // namespace Ra

template <>
struct OpenMesh::vector_traits<Ra::Core::TopoVector3> {
    /// Type of the vector class
    using vector_type = Ra::Core::Vector3;

    /// Type of the scalar value
    using value_type = Scalar;

    /// size/dimension of the vector
    static const size_t size_ = 3;

    /// size/dimension of the vector
    static inline size_t size() { return size_; }
};

namespace Ra {
namespace Core {

// Define an OpenMesh TriMesh structure according to
// http://openmesh.org/Documentation/OpenMesh-2.1-Documentation/mesh_type.html
// Attributes define data store on structure.

struct TopologicalMeshTraits : public OpenMesh::DefaultTraits {
    using Point = TopoVector3;
    using Normal = TopoVector3;

    VertexAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
    FaceAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );
    EdgeAttributes( OpenMesh::Attributes::Status );
    HalfedgeAttributes( OpenMesh::Attributes::Status | OpenMesh::Attributes::Normal );

    VertexTraits {
      private:
        Index m_index;

      public:
        /// If index valid, normal is TriMesh vertex normal
        inline Index getIndex() { return m_index; }
        inline void setIndex( Index index ) { m_index = index; }
    };

    HalfedgeTraits {
      private:
        Index m_index;

      public:
        /// if Index valid, normal and other data of halfedge is TriMesh vertex data
        inline Index getIndex() { return m_index; }
        inline void setIndex( Index index ) { m_index = index; }
    };

  public:
};

class TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT<TopologicalMeshTraits> {
    using base = OpenMesh::PolyMesh_ArrayKernelT<TopologicalMeshTraits>;
    using base::PolyMesh_ArrayKernelT;

  public:
    inline Normal& normal( VertexHandle vh, FaceHandle fh ) {
        // find halfedge that point to vh and member of fh
        return property( halfedge_normals_pph(), halfedge_handle( vh, fh ) );
    }

    using base::halfedge_handle;
    inline HalfedgeHandle halfedge_handle( VertexHandle vh, FaceHandle fh ) {

        for ( VertexIHalfedgeIter vih_it = vih_iter( vh ); vih_it.is_valid(); ++vih_it )
        {
            if ( face_handle( *vih_it ) == fh )
            {
                return *vih_it;
            }
        }
        return HalfedgeHandle();
    }
};
} // namespace Core
} // namespace Ra

#endif // TOPOLOGICALMESH_H
<|endoftext|>


<commit_before>//===- TwoIDPass.cpp - Implementation of Two-Class CFI policy -------------===//
//
// This pass instruments LLVM IR with the Two-Class CFI Policy. It
// inherits from ICfiPass.
//
// The instrumented code should follow these rules:
// 1. every indirect call or branch can target every function or
//    indirectly targetable basic block
// 2. every return can target every call site
//
//===----------------------------------------------------------------------===//

#include "cfi/ICfiPass.h"
#include "cfi/TwoIDPass.h"
#include <sstream>

using namespace llvm;

namespace cfi {

    /**
     * @brief initializes the Two-Class CFI pass
     *
     * @arg M - current module
     */
    TwoIDPass::TwoIDPass(Module &M)
    {
        mod = &M;
        this->numFunPointers = 0;
    }

    void TwoIDPass::findFunctionPointerArgs(CallInst* CI)
    {
       if (CI == NULL)
          return;

       unsigned num_args = CI->getNumArgOperands();
       unsigned i;

       for (i = 0; i < num_args; i++)
       {
          Type* arg_type = CI->getArgOperand(i)->getType();

          if (PointerType * PT = dyn_cast<PointerType>(arg_type))
          {
             Type* elem_type = PT->getElementType();
             if (FunctionType * FT = dyn_cast<FunctionType>(elem_type))
             {
                numFunPointers++;
             }

          }
       }
    }

    /**
     * @brief finds all transfer sites and targets and populates
     * jmpSites, jmpTars, retSites, retTars
     *
     * @arg ctf - call target finder, provided by DSA,
     * should be null for this pass
     *
     * @return void
     */
    void TwoIDPass::findAllTargets(CTF &ctf)
    {
        Module::iterator MB, ME;
        //iterate through functions in module
        for (MB = mod->begin(), ME = mod->end(); MB != ME; MB++)
        {
            Function *F = &*MB;

            //iterate through basic blocks in function
            Function::iterator FB, FE;
            for (FB = F->begin(), FE = F->end(); FB != FE; FB++)
            {
                BasicBlock::iterator BB, BE;
                for(BB = FB->begin(), BE = FB->end(); BB != BE; BB++)
                {
                    Instruction *I = &*BB;

                    //found: call site
                    if (CallInst* callInst = dyn_cast<CallInst>(I))
                    {
                        //TODO: move this once design finalized.

                        findFunctionPointerArgs(callInst);

                        Function *calledFunc = callInst->getCalledFunction();
                        //found: indirect call site
                        if (calledFunc == NULL)
                        {
                            jmpSites.insert(I);
                        }
                        else
                        {
                            if (calledFunc->isIntrinsic() ||
                                calledFunc->isDeclaration())
                                continue;
                        }
                        //call sites are return targets (call or indirect call)
                        retTars.insert(I);
                    }
                    //found: indirect branch site
                    else if (dyn_cast<IndirectBrInst>(I))
                    {
                        jmpSites.insert(I);
                    }
                    //found: return site
                    else if (dyn_cast<ReturnInst>(I))
                    {
                        if (F->getName() != "main")
                        {
                            retSites.insert(I);
                        }
                    }
                }
            }

            if (F->isDeclaration())
                continue;

            //find all indirect call and branch targets (basic blocks)
            BBSet indTargets = findIndTargets(*F);

            //for all targets in indTargets, add first instruction of
            //basic block to jmpTars
            BBSet::iterator BB, BE;
            for (BB = indTargets.begin(), BE = indTargets.end();
                    BB != BE; BB++)
            {
                BasicBlock::iterator II = (*BB)->begin();
                jmpTars.insert(II);
            }
        }
    }

    /**
     * @brief finds all indirect targets in given function
     *
     * @arg F - function
     *
     * @return set of indirectly targetable basic blocks,
     * including entry block, of given function
     */
    BBSet TwoIDPass::findIndTargets(Function &F)
    {
        BBSet indTargets;
        if (F.getName() != "main")
            indTargets.insert(&F.getEntryBlock());

        //iterate over basic blocks in function
        Function::iterator FB, FE;
        for (FB = F.begin(), FE = F.end(); FB != FE; FB++)
        {
            BasicBlock *B = &*FB;

            //check if basic block ends with indirect branch
            //Future: add other checks: exceptions, longjumps, trampolines?
            if (TerminatorInst *TI = B->getTerminator())
            {
                if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(TI))
                {
                    //add all possible successors to indBrDestMap
                    int n = IBI->getNumSuccessors();
                    for (int j = 0; j < n; j++)
                    {
                        indTargets.insert(IBI->getSuccessor(j));
                    }
                }
            }
        }
        return indTargets;
    }

    /**
     * @brief generate target IDs, populates jmpMap and retMap
     *
     * @return void
     */
    void TwoIDPass::generateDestIDs()
    {
        InstSet::iterator IB, IE;

        //make sure ID is smaller than MAX
        jmpID = rand() % MAX;
        for (IB = jmpTars.begin(), IE = jmpTars.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            jmpMap[K] = jmpID;
        }

        //ensure two IDs are unique
        do {
            retID = rand() % MAX;
        } while (retID == jmpID);

        for (IB = retTars.begin(), IE = retTars.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            retMap[K] = retID;
        }
    }

    /**
     * @brief generate transfer site check IDs, populates jmpCheckMap
     * and retCheckMap
     *
     * @return void
     */
    void TwoIDPass::generateCheckIDs()
    {
        InstSet::iterator IB, IE;

        for (IB = jmpSites.begin(), IE = jmpSites.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            std::set<int> *idset = &jmpCheckMap[K];
            if (idset->find(jmpID) != idset->end()) // idset.contains(ID)
                continue;
            else
                idset->insert(jmpID);
        }

        for (IB = retSites.begin(), IE = retSites.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            std::set<int> *idset = &retCheckMap[K];
            if (idset->find(retID) != idset->end()) // idset.contains(ID)
                continue;
            else
                idset->insert(retID);
        }
    }

    /**
     * @brief insert IDs and checks into IR
     *
     * @return void
     */
    void TwoIDPass::lowerChecksAndIDs()
    {
        CFILowering cfil = CFILowering(*mod);
        cfil.insertIDs(jmpMap, false);
        cfil.insertIDs(retMap, true);
        cfil.insertChecks(jmpCheckMap);
        cfil.insertChecks(retCheckMap);
    }

    /**
     * @brief get statistics for this pass
     *
     * @return string representation of stats
     */
    std::string TwoIDPass::getStats()
    {
        int num_sites = 0;
        int cumulative_targets = 0;

        float avg_tars  = 0.0;
        int min_tars = 0;
        int max_tars  = 0;

        //iterate over monitor code sites
        InstIDSetMap::iterator IB, IE;
        for (IB = jmpCheckMap.begin(), IE = jmpCheckMap.end();
             IB != IE; IB++)
        {
            num_sites++;
            int num_tars = jmpTars.size();

            min_tars = min_tars == 0 ? num_tars : fmin(min_tars, num_tars);
            max_tars = fmax(max_tars, num_tars);
            cumulative_targets += num_tars;
        }

        for (IB = retCheckMap.begin(), IE = retCheckMap.end();
             IB != IE; IB++)
        {
            num_sites++;
            int num_tars = retTars.size();

            min_tars = min_tars == 0 ? num_tars : fmin(min_tars, num_tars);
            max_tars = fmax(max_tars, num_tars);
            cumulative_targets += num_tars;
        }

        avg_tars = float(cumulative_targets)/float(num_sites);

        std::ostringstream resultStream;

        resultStream << "Two ID Stats:\n";
        resultStream << "\tnum_sites = " << num_sites << "\n";
        resultStream << "\tcumulative_targets = " << cumulative_targets << "\n";
        resultStream << "\tTargets Per Callsite:\n";
        resultStream << "\t\tavg = " << avg_tars << "\n";
        resultStream << "\t\tmin = " << min_tars << "\n";
        resultStream << "\t\tmax = " << max_tars << "\n";

        resultStream << "\t\tnumber of function pointer args: " << numFunPointers << "\n";

        return resultStream.str();
    }

    /**
     * @brief prints debug info for this pass
     *
     * @return void
     */
    void TwoIDPass::print()
    {
        print_ID_maps(jmpMap, "jmpMap");
        print_ID_maps(retMap, "retMap");
        print_ID_check_maps(jmpCheckMap, "jmpCheckMap");
        print_ID_check_maps(retCheckMap, "retCheckMap");
    }
}
<commit_msg>elimination of internal fn pointers<commit_after>//===- TwoIDPass.cpp - Implementation of Two-Class CFI policy -------------===//
//
// This pass instruments LLVM IR with the Two-Class CFI Policy. It
// inherits from ICfiPass.
//
// The instrumented code should follow these rules:
// 1. every indirect call or branch can target every function or
//    indirectly targetable basic block
// 2. every return can target every call site
//
//===----------------------------------------------------------------------===//

#include "cfi/ICfiPass.h"
#include "cfi/TwoIDPass.h"
#include <sstream>

using namespace llvm;

namespace cfi {

    /**
     * @brief initializes the Two-Class CFI pass
     *
     * @arg M - current module
     */
    TwoIDPass::TwoIDPass(Module &M)
    {
        mod = &M;
        this->numFunPointers = 0;
    }

    void TwoIDPass::findFunctionPointerArgs(CallInst* CI)
    {
       if (CI == NULL)
          return;

       unsigned num_args = CI->getNumArgOperands();
       unsigned i;

       for (i = 0; i < num_args; i++)
       {
          Type* arg_type = CI->getArgOperand(i)->getType();

          if (PointerType * PT = dyn_cast<PointerType>(arg_type))
          {
             Type* elem_type = PT->getElementType();
             if (FunctionType * FT = dyn_cast<FunctionType>(elem_type))
             {
                Function *calledFunc = CI->getCalledFunction();
                if (calledFunc != NULL && calledFunc->isDeclaration())
                {
                   errs() << calledFunc->getName() << "\n";
                   numFunPointers++;
                }
             }
          }
       }
    }

    /**
     * @brief finds all transfer sites and targets and populates
     * jmpSites, jmpTars, retSites, retTars
     *
     * @arg ctf - call target finder, provided by DSA,
     * should be null for this pass
     *
     * @return void
     */
    void TwoIDPass::findAllTargets(CTF &ctf)
    {
        Module::iterator MB, ME;
        //iterate through functions in module
        for (MB = mod->begin(), ME = mod->end(); MB != ME; MB++)
        {
            Function *F = &*MB;

            //iterate through basic blocks in function
            Function::iterator FB, FE;
            for (FB = F->begin(), FE = F->end(); FB != FE; FB++)
            {
                BasicBlock::iterator BB, BE;
                for(BB = FB->begin(), BE = FB->end(); BB != BE; BB++)
                {
                    Instruction *I = &*BB;

                    //found: call site
                    if (CallInst* callInst = dyn_cast<CallInst>(I))
                    {
                        //TODO: move this once design finalized.

                        findFunctionPointerArgs(callInst);

                        Function *calledFunc = callInst->getCalledFunction();
                        //found: indirect call site
                        if (calledFunc == NULL)
                        {
                            jmpSites.insert(I);
                        }
                        else
                        {
                            if (calledFunc->isIntrinsic() ||
                                calledFunc->isDeclaration())
                                continue;
                        }
                        //call sites are return targets (call or indirect call)
                        retTars.insert(I);
                    }
                    //found: indirect branch site
                    else if (dyn_cast<IndirectBrInst>(I))
                    {
                        jmpSites.insert(I);
                    }
                    //found: return site
                    else if (dyn_cast<ReturnInst>(I))
                    {
                        if (F->getName() != "main")
                        {
                            retSites.insert(I);
                        }
                    }
                }
            }

            if (F->isDeclaration())
                continue;

            //find all indirect call and branch targets (basic blocks)
            BBSet indTargets = findIndTargets(*F);

            //for all targets in indTargets, add first instruction of
            //basic block to jmpTars
            BBSet::iterator BB, BE;
            for (BB = indTargets.begin(), BE = indTargets.end();
                    BB != BE; BB++)
            {
                BasicBlock::iterator II = (*BB)->begin();
                jmpTars.insert(II);
            }
        }
    }

    /**
     * @brief finds all indirect targets in given function
     *
     * @arg F - function
     *
     * @return set of indirectly targetable basic blocks,
     * including entry block, of given function
     */
    BBSet TwoIDPass::findIndTargets(Function &F)
    {
        BBSet indTargets;
        if (F.getName() != "main")
            indTargets.insert(&F.getEntryBlock());

        //iterate over basic blocks in function
        Function::iterator FB, FE;
        for (FB = F.begin(), FE = F.end(); FB != FE; FB++)
        {
            BasicBlock *B = &*FB;

            //check if basic block ends with indirect branch
            //Future: add other checks: exceptions, longjumps, trampolines?
            if (TerminatorInst *TI = B->getTerminator())
            {
                if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(TI))
                {
                    //add all possible successors to indBrDestMap
                    int n = IBI->getNumSuccessors();
                    for (int j = 0; j < n; j++)
                    {
                        indTargets.insert(IBI->getSuccessor(j));
                    }
                }
            }
        }
        return indTargets;
    }

    /**
     * @brief generate target IDs, populates jmpMap and retMap
     *
     * @return void
     */
    void TwoIDPass::generateDestIDs()
    {
        InstSet::iterator IB, IE;

        //make sure ID is smaller than MAX
        jmpID = rand() % MAX;
        for (IB = jmpTars.begin(), IE = jmpTars.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            jmpMap[K] = jmpID;
        }

        //ensure two IDs are unique
        do {
            retID = rand() % MAX;
        } while (retID == jmpID);

        for (IB = retTars.begin(), IE = retTars.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            retMap[K] = retID;
        }
    }

    /**
     * @brief generate transfer site check IDs, populates jmpCheckMap
     * and retCheckMap
     *
     * @return void
     */
    void TwoIDPass::generateCheckIDs()
    {
        InstSet::iterator IB, IE;

        for (IB = jmpSites.begin(), IE = jmpSites.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            std::set<int> *idset = &jmpCheckMap[K];
            if (idset->find(jmpID) != idset->end()) // idset.contains(ID)
                continue;
            else
                idset->insert(jmpID);
        }

        for (IB = retSites.begin(), IE = retSites.end(); IB != IE; IB++)
        {
            Instruction* K = *IB;
            std::set<int> *idset = &retCheckMap[K];
            if (idset->find(retID) != idset->end()) // idset.contains(ID)
                continue;
            else
                idset->insert(retID);
        }
    }

    /**
     * @brief insert IDs and checks into IR
     *
     * @return void
     */
    void TwoIDPass::lowerChecksAndIDs()
    {
        CFILowering cfil = CFILowering(*mod);
        cfil.insertIDs(jmpMap, false);
        cfil.insertIDs(retMap, true);
        cfil.insertChecks(jmpCheckMap);
        cfil.insertChecks(retCheckMap);
    }

    /**
     * @brief get statistics for this pass
     *
     * @return string representation of stats
     */
    std::string TwoIDPass::getStats()
    {
        int num_sites = 0;
        int cumulative_targets = 0;

        float avg_tars  = 0.0;
        int min_tars = 0;
        int max_tars  = 0;

        //iterate over monitor code sites
        InstIDSetMap::iterator IB, IE;
        for (IB = jmpCheckMap.begin(), IE = jmpCheckMap.end();
             IB != IE; IB++)
        {
            num_sites++;
            int num_tars = jmpTars.size();

            min_tars = min_tars == 0 ? num_tars : fmin(min_tars, num_tars);
            max_tars = fmax(max_tars, num_tars);
            cumulative_targets += num_tars;
        }

        for (IB = retCheckMap.begin(), IE = retCheckMap.end();
             IB != IE; IB++)
        {
            num_sites++;
            int num_tars = retTars.size();

            min_tars = min_tars == 0 ? num_tars : fmin(min_tars, num_tars);
            max_tars = fmax(max_tars, num_tars);
            cumulative_targets += num_tars;
        }

        avg_tars = float(cumulative_targets)/float(num_sites);

        std::ostringstream resultStream;

        resultStream << "Two ID Stats:\n";
        resultStream << "\tnum_sites = " << num_sites << "\n";
        resultStream << "\tcumulative_targets = " << cumulative_targets << "\n";
        resultStream << "\tTargets Per Callsite:\n";
        resultStream << "\t\tavg = " << avg_tars << "\n";
        resultStream << "\t\tmin = " << min_tars << "\n";
        resultStream << "\t\tmax = " << max_tars << "\n";

        resultStream << "\t\tnumber of function pointer args: " << numFunPointers << "\n";

        return resultStream.str();
    }

    /**
     * @brief prints debug info for this pass
     *
     * @return void
     */
    void TwoIDPass::print()
    {
        print_ID_maps(jmpMap, "jmpMap");
        print_ID_maps(retMap, "retMap");
        print_ID_check_maps(jmpCheckMap, "jmpCheckMap");
        print_ID_check_maps(retCheckMap, "retCheckMap");
    }
}
<|endoftext|>


<commit_before>//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the generic AliasAnalysis interface which is used as the
// common interface used by all clients and implementations of alias analysis.
//
// This file also implements the default version of the AliasAnalysis interface
// that is to be used when no other implementation is specified.  This does some
// simple tests that detect obvious cases: two different global pointers cannot
// alias, a global cannot alias a malloc, two different mallocs cannot alias,
// etc.
//
// This alias analysis implementation really isn't very good for anything, but
// it is very fast, and makes a nice clean default implementation.  Because it
// handles lots of little corner cases, other, more complex, alias analysis
// implementations may choose to rely on this pass to resolve these simple and
// easy cases.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Pass.h"
#include "llvm/BasicBlock.h"
#include "llvm/Function.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;

// Register the AliasAnalysis interface, providing a nice name to refer to.
static RegisterAnalysisGroup<AliasAnalysis> Z("Alias Analysis");
char AliasAnalysis::ID = 0;

//===----------------------------------------------------------------------===//
// Default chaining methods
//===----------------------------------------------------------------------===//

AliasAnalysis::AliasResult
AliasAnalysis::alias(const Value *V1, unsigned V1Size,
                     const Value *V2, unsigned V2Size) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->alias(V1, V1Size, V2, V2Size);
}

void AliasAnalysis::getMustAliases(Value *P, std::vector<Value*> &RetVals) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->getMustAliases(P, RetVals);
}

bool AliasAnalysis::pointsToConstantMemory(const Value *P) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->pointsToConstantMemory(P);
}

bool AliasAnalysis::hasNoModRefInfoForCalls() const {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->hasNoModRefInfoForCalls();
}

void AliasAnalysis::deleteValue(Value *V) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  AA->deleteValue(V);
}

void AliasAnalysis::copyValue(Value *From, Value *To) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  AA->copyValue(From, To);
}

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(CallSite CS1, CallSite CS2) {
  // FIXME: we can do better.
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->getModRefInfo(CS1, CS2);
}

//===----------------------------------------------------------------------===//
// AliasAnalysis non-virtual helper method implementation
//===----------------------------------------------------------------------===//

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(LoadInst *L, Value *P, unsigned Size) {
  return alias(L->getOperand(0), TD->getTypeStoreSize(L->getType()),
               P, Size) ? Ref : NoModRef;
}

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) {
  // If the stored address cannot alias the pointer in question, then the
  // pointer cannot be modified by the store.
  if (!alias(S->getOperand(1),
             TD->getTypeStoreSize(S->getOperand(0)->getType()), P, Size))
    return NoModRef;

  // If the pointer is a pointer to constant memory, then it could not have been
  // modified by this store.
  return pointsToConstantMemory(P) ? NoModRef : Mod;
}

AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(CallSite CS,
                                 std::vector<PointerAccessInfo> *Info) {
  if (CS.doesNotAccessMemory())
    // Can't do better than this.
    return DoesNotAccessMemory;
  ModRefBehavior MRB = getModRefBehavior(CS.getCalledFunction(), Info);
  if (MRB != DoesNotAccessMemory && CS.onlyReadsMemory())
    return OnlyReadsMemory;
  return MRB;
}

AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(Function *F,
                                 std::vector<PointerAccessInfo> *Info) {
  if (F && F->doesNotAccessMemory())
    // Can't do better than this.
    return DoesNotAccessMemory;
  return UnknownModRefBehavior;
}

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  ModRefResult Mask = ModRef;
  ModRefBehavior MRB = getModRefBehavior(CS);
  if (MRB == OnlyReadsMemory)
    Mask = Ref;
  else if (MRB == DoesNotAccessMemory)
    return NoModRef;
  else if (MRB == AliasAnalysis::AccessesArguments) {
    bool doesAlias = false;
    for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
         AI != AE; ++AI)
      if (alias(*AI, ~0U, P, Size) != NoAlias) {
        doesAlias = true;
        break;
      }

    if (!doesAlias)
      return NoModRef;
  }

  if (!AA) return Mask;

  // If P points to a constant memory location, the call definitely could not
  // modify the memory location.
  if ((Mask & Mod) && AA->pointsToConstantMemory(P))
    Mask = ModRefResult(Mask & ~Mod);

  return ModRefResult(Mask & AA->getModRefInfo(CS, P, Size));
}

// AliasAnalysis destructor: DO NOT move this to the header file for
// AliasAnalysis or else clients of the AliasAnalysis class may not depend on
// the AliasAnalysis.o file in the current .a file, causing alias analysis
// support to not be included in the tool correctly!
//
AliasAnalysis::~AliasAnalysis() {}

/// InitializeAliasAnalysis - Subclasses must call this method to initialize the
/// AliasAnalysis interface before any other methods are called.
///
void AliasAnalysis::InitializeAliasAnalysis(Pass *P) {
  TD = &P->getAnalysis<TargetData>();
  AA = &P->getAnalysis<AliasAnalysis>();
}

// getAnalysisUsage - All alias analysis implementations should invoke this
// directly (using AliasAnalysis::getAnalysisUsage(AU)) to make sure that
// TargetData is required by the pass.
void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<TargetData>();            // All AA's need TargetData.
  AU.addRequired<AliasAnalysis>();         // All AA's chain
}

/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
                                        const Value *Ptr, unsigned Size) {
  return canInstructionRangeModify(BB.front(), BB.back(), Ptr, Size);
}

/// canInstructionRangeModify - Return true if it is possible for the execution
/// of the specified instructions to modify the value pointed to by Ptr.  The
/// instructions to consider are all of the instructions in the range of [I1,I2]
/// INCLUSIVE.  I1 and I2 must be in the same basic block.
///
bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1,
                                              const Instruction &I2,
                                              const Value *Ptr, unsigned Size) {
  assert(I1.getParent() == I2.getParent() &&
         "Instructions not in same basic block!");
  BasicBlock::iterator I = const_cast<Instruction*>(&I1);
  BasicBlock::iterator E = const_cast<Instruction*>(&I2);
  ++E;  // Convert from inclusive to exclusive range.

  for (; I != E; ++I) // Check every instruction in range
    if (getModRefInfo(I, const_cast<Value*>(Ptr), Size) & Mod)
      return true;
  return false;
}

/// isNoAliasCall - Return true if this pointer is returned by a noalias
/// function.
bool llvm::isNoAliasCall(const Value *V) {
  if (isa<CallInst>(V) || isa<InvokeInst>(V))
    return CallSite(const_cast<Instruction*>(cast<Instruction>(V)))
      .paramHasAttr(0, Attribute::NoAlias);
  return false;
}

/// isIdentifiedObject - Return true if this pointer refers to a distinct and
/// identifiable object.  This returns true for:
///    Global Variables and Functions
///    Allocas and Mallocs
///    ByVal and NoAlias Arguments
///    NoAlias returns
///
bool llvm::isIdentifiedObject(const Value *V) {
  if (isa<GlobalValue>(V) || isa<AllocationInst>(V) || isNoAliasCall(V))
    return true;
  if (const Argument *A = dyn_cast<Argument>(V))
    return A->hasNoAliasAttr() || A->hasByValAttr();
  return false;
}

// Because of the way .a files work, we must force the BasicAA implementation to
// be pulled in if the AliasAnalysis classes are pulled in.  Otherwise we run
// the risk of AliasAnalysis being used, but the default implementation not
// being linked into the tool that uses it.
DEFINING_FILE_FOR(AliasAnalysis)
<commit_msg>If a function only reads memory, then we know that... it only reads memory!  The other change has no functional effect, it just seems more logical to go in order of decreasing knowledge.<commit_after>//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the generic AliasAnalysis interface which is used as the
// common interface used by all clients and implementations of alias analysis.
//
// This file also implements the default version of the AliasAnalysis interface
// that is to be used when no other implementation is specified.  This does some
// simple tests that detect obvious cases: two different global pointers cannot
// alias, a global cannot alias a malloc, two different mallocs cannot alias,
// etc.
//
// This alias analysis implementation really isn't very good for anything, but
// it is very fast, and makes a nice clean default implementation.  Because it
// handles lots of little corner cases, other, more complex, alias analysis
// implementations may choose to rely on this pass to resolve these simple and
// easy cases.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Pass.h"
#include "llvm/BasicBlock.h"
#include "llvm/Function.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;

// Register the AliasAnalysis interface, providing a nice name to refer to.
static RegisterAnalysisGroup<AliasAnalysis> Z("Alias Analysis");
char AliasAnalysis::ID = 0;

//===----------------------------------------------------------------------===//
// Default chaining methods
//===----------------------------------------------------------------------===//

AliasAnalysis::AliasResult
AliasAnalysis::alias(const Value *V1, unsigned V1Size,
                     const Value *V2, unsigned V2Size) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->alias(V1, V1Size, V2, V2Size);
}

void AliasAnalysis::getMustAliases(Value *P, std::vector<Value*> &RetVals) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->getMustAliases(P, RetVals);
}

bool AliasAnalysis::pointsToConstantMemory(const Value *P) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->pointsToConstantMemory(P);
}

bool AliasAnalysis::hasNoModRefInfoForCalls() const {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->hasNoModRefInfoForCalls();
}

void AliasAnalysis::deleteValue(Value *V) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  AA->deleteValue(V);
}

void AliasAnalysis::copyValue(Value *From, Value *To) {
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  AA->copyValue(From, To);
}

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(CallSite CS1, CallSite CS2) {
  // FIXME: we can do better.
  assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
  return AA->getModRefInfo(CS1, CS2);
}

//===----------------------------------------------------------------------===//
// AliasAnalysis non-virtual helper method implementation
//===----------------------------------------------------------------------===//

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(LoadInst *L, Value *P, unsigned Size) {
  return alias(L->getOperand(0), TD->getTypeStoreSize(L->getType()),
               P, Size) ? Ref : NoModRef;
}

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) {
  // If the stored address cannot alias the pointer in question, then the
  // pointer cannot be modified by the store.
  if (!alias(S->getOperand(1),
             TD->getTypeStoreSize(S->getOperand(0)->getType()), P, Size))
    return NoModRef;

  // If the pointer is a pointer to constant memory, then it could not have been
  // modified by this store.
  return pointsToConstantMemory(P) ? NoModRef : Mod;
}

AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(CallSite CS,
                                 std::vector<PointerAccessInfo> *Info) {
  if (CS.doesNotAccessMemory())
    // Can't do better than this.
    return DoesNotAccessMemory;
  ModRefBehavior MRB = getModRefBehavior(CS.getCalledFunction(), Info);
  if (MRB != DoesNotAccessMemory && CS.onlyReadsMemory())
    return OnlyReadsMemory;
  return MRB;
}

AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(Function *F,
                                 std::vector<PointerAccessInfo> *Info) {
  if (F) {
    if (F->doesNotAccessMemory())
      // Can't do better than this.
      return DoesNotAccessMemory;
    else if (F->onlyReadsMemory())
      return OnlyReadsMemory;
  }
  return UnknownModRefBehavior;
}

AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
  ModRefResult Mask = ModRef;
  ModRefBehavior MRB = getModRefBehavior(CS);
  if (MRB == DoesNotAccessMemory)
    return NoModRef;
  else if (MRB == OnlyReadsMemory)
    Mask = Ref;
  else if (MRB == AliasAnalysis::AccessesArguments) {
    bool doesAlias = false;
    for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
         AI != AE; ++AI)
      if (alias(*AI, ~0U, P, Size) != NoAlias) {
        doesAlias = true;
        break;
      }

    if (!doesAlias)
      return NoModRef;
  }

  if (!AA) return Mask;

  // If P points to a constant memory location, the call definitely could not
  // modify the memory location.
  if ((Mask & Mod) && AA->pointsToConstantMemory(P))
    Mask = ModRefResult(Mask & ~Mod);

  return ModRefResult(Mask & AA->getModRefInfo(CS, P, Size));
}

// AliasAnalysis destructor: DO NOT move this to the header file for
// AliasAnalysis or else clients of the AliasAnalysis class may not depend on
// the AliasAnalysis.o file in the current .a file, causing alias analysis
// support to not be included in the tool correctly!
//
AliasAnalysis::~AliasAnalysis() {}

/// InitializeAliasAnalysis - Subclasses must call this method to initialize the
/// AliasAnalysis interface before any other methods are called.
///
void AliasAnalysis::InitializeAliasAnalysis(Pass *P) {
  TD = &P->getAnalysis<TargetData>();
  AA = &P->getAnalysis<AliasAnalysis>();
}

// getAnalysisUsage - All alias analysis implementations should invoke this
// directly (using AliasAnalysis::getAnalysisUsage(AU)) to make sure that
// TargetData is required by the pass.
void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<TargetData>();            // All AA's need TargetData.
  AU.addRequired<AliasAnalysis>();         // All AA's chain
}

/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the value pointed to by Ptr.
///
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
                                        const Value *Ptr, unsigned Size) {
  return canInstructionRangeModify(BB.front(), BB.back(), Ptr, Size);
}

/// canInstructionRangeModify - Return true if it is possible for the execution
/// of the specified instructions to modify the value pointed to by Ptr.  The
/// instructions to consider are all of the instructions in the range of [I1,I2]
/// INCLUSIVE.  I1 and I2 must be in the same basic block.
///
bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1,
                                              const Instruction &I2,
                                              const Value *Ptr, unsigned Size) {
  assert(I1.getParent() == I2.getParent() &&
         "Instructions not in same basic block!");
  BasicBlock::iterator I = const_cast<Instruction*>(&I1);
  BasicBlock::iterator E = const_cast<Instruction*>(&I2);
  ++E;  // Convert from inclusive to exclusive range.

  for (; I != E; ++I) // Check every instruction in range
    if (getModRefInfo(I, const_cast<Value*>(Ptr), Size) & Mod)
      return true;
  return false;
}

/// isNoAliasCall - Return true if this pointer is returned by a noalias
/// function.
bool llvm::isNoAliasCall(const Value *V) {
  if (isa<CallInst>(V) || isa<InvokeInst>(V))
    return CallSite(const_cast<Instruction*>(cast<Instruction>(V)))
      .paramHasAttr(0, Attribute::NoAlias);
  return false;
}

/// isIdentifiedObject - Return true if this pointer refers to a distinct and
/// identifiable object.  This returns true for:
///    Global Variables and Functions
///    Allocas and Mallocs
///    ByVal and NoAlias Arguments
///    NoAlias returns
///
bool llvm::isIdentifiedObject(const Value *V) {
  if (isa<GlobalValue>(V) || isa<AllocationInst>(V) || isNoAliasCall(V))
    return true;
  if (const Argument *A = dyn_cast<Argument>(V))
    return A->hasNoAliasAttr() || A->hasByValAttr();
  return false;
}

// Because of the way .a files work, we must force the BasicAA implementation to
// be pulled in if the AliasAnalysis classes are pulled in.  Otherwise we run
// the risk of AliasAnalysis being used, but the default implementation not
// being linked into the tool that uses it.
DEFINING_FILE_FOR(AliasAnalysis)
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// FFTFrame implementation using FFmpeg's RDFT algorithm,
// suitable for use on Windows and Linux.

#include "config.h"

#if ENABLE(WEB_AUDIO)

#if USE(WEBAUDIO_FFMPEG)

#include "platform/audio/FFTFrame.h"

#include "platform/audio/VectorMath.h"

extern "C" {
    #include <libavcodec/avfft.h>
}

#include "wtf/MathExtras.h"

namespace {

struct FFTComplexProxy {
    int16_t re;
    int16_t im;
};

struct FFTContextProxy {
    int nbits;
    int inverse;
    uint16_t* revtab;
    FFTComplexProxy* tmpBuf;
    int mdctSize;
    int mdctBits;
    void* tcos;
    void* tsin;
    void (*fftPermute)();
    void (*fftCalc)();
    void (*imdctCalc)();
    void (*imdctHalf)();
    void (*mdctCalc)();
    void (*mdctCalcw)();
    int fftPermutation;
    int mdctPermutation;
};

struct RDFTContextProxy {
    int nbits;
    int inverse;
    int signConvention;
    const void* tcos;
    const void* tsin;
    FFTContextProxy fft;
    void (*rdft_calc)();
};

}

namespace WebCore {

#if !ASSERT_DISABLED
const int kMaxFFTPow2Size = 24;
#endif

// Normal constructor: allocates for a given fftSize.
FFTFrame::FFTFrame(unsigned fftSize)
    : m_FFTSize(fftSize)
    , m_log2FFTSize(static_cast<unsigned>(log2(fftSize)))
    , m_forwardContext(0)
    , m_inverseContext(0)
    , m_complexData(fftSize)
    , m_realData(fftSize / 2)
    , m_imagData(fftSize / 2)
{
    // We only allow power of two.
    ASSERT(1UL << m_log2FFTSize == m_FFTSize);

    m_forwardContext = contextForSize(fftSize, DFT_R2C);
    m_inverseContext = contextForSize(fftSize, IDFT_C2R);
}

// Creates a blank/empty frame (interpolate() must later be called).
FFTFrame::FFTFrame()
    : m_FFTSize(0)
    , m_log2FFTSize(0)
    , m_forwardContext(0)
    , m_inverseContext(0)
{
}

// Copy constructor.
FFTFrame::FFTFrame(const FFTFrame& frame)
    : m_FFTSize(frame.m_FFTSize)
    , m_log2FFTSize(frame.m_log2FFTSize)
    , m_forwardContext(0)
    , m_inverseContext(0)
    , m_complexData(frame.m_FFTSize)
    , m_realData(frame.m_FFTSize / 2)
    , m_imagData(frame.m_FFTSize / 2)
{
    m_forwardContext = contextForSize(m_FFTSize, DFT_R2C);
    m_inverseContext = contextForSize(m_FFTSize, IDFT_C2R);

    // Copy/setup frame data.
    unsigned nbytes = sizeof(float) * (m_FFTSize / 2);
    memcpy(realData(), frame.realData(), nbytes);
    memcpy(imagData(), frame.imagData(), nbytes);
}

void FFTFrame::initialize()
{
}

void FFTFrame::cleanup()
{
}

FFTFrame::~FFTFrame()
{
    av_rdft_end(m_forwardContext);
    av_rdft_end(m_inverseContext);
}

void FFTFrame::multiply(const FFTFrame& frame)
{
    FFTFrame& frame1 = *this;
    FFTFrame& frame2 = const_cast<FFTFrame&>(frame);

    float* realP1 = frame1.realData();
    float* imagP1 = frame1.imagData();
    const float* realP2 = frame2.realData();
    const float* imagP2 = frame2.imagData();

    unsigned halfSize = fftSize() / 2;
    float real0 = realP1[0];
    float imag0 = imagP1[0];

    VectorMath::zvmul(realP1, imagP1, realP2, imagP2, realP1, imagP1, halfSize);

    // Multiply the packed DC/nyquist component
    realP1[0] = real0 * realP2[0];
    imagP1[0] = imag0 * imagP2[0];

    // Scale accounts the peculiar scaling of vecLib on the Mac.
    // This ensures the right scaling all the way back to inverse FFT.
    // FIXME: if we change the scaling on the Mac then this scale
    // factor will need to change too.
    float scale = 0.5f;

    VectorMath::vsmul(realP1, 1, &scale, realP1, 1, halfSize);
    VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, halfSize);
}

#if OS(WIN)
// On Windows, the following pragmas are equivalent to compiling the code with /fp:fast. The
// following code does not need precise FP semantics, and speed is critical here. See
// crbug.com/316740 and crrev.com/116823002.
#pragma float_control(except, off, push)
#pragma float_control(precise, off, push)
#pragma fp_contract(on)
#pragma fenv_access(off)
#endif

void FFTFrame::doFFT(const float* data)
{
    // Copy since processing is in-place.
    float* p = m_complexData.data();
    memcpy(p, data, sizeof(float) * m_FFTSize);

    // Compute Forward transform.
    av_rdft_calc(m_forwardContext, p);

    // De-interleave to separate real and complex arrays.
    int len = m_FFTSize / 2;

    // FIXME: see above comment in multiply() about scaling.
    const float scale = 2.0f;

    float* real = m_realData.data();
    float* imag = m_imagData.data();
    for (int i = 0; i < len; ++i) {
        int baseComplexIndex = 2 * i;
        // m_realData[0] is the DC component and m_imagData[0] is the nyquist component
        // since the interleaved complex data is packed.
        real[i] = scale * p[baseComplexIndex];
        imag[i] = scale * p[baseComplexIndex + 1];
    }
}

void FFTFrame::doInverseFFT(float* data)
{
    // Prepare interleaved data.
    float* interleavedData = getUpToDateComplexData();

    // Compute inverse transform.
    av_rdft_calc(m_inverseContext, interleavedData);

    // Scale so that a forward then inverse FFT yields exactly the original data.
    const float scale = 1.0 / m_FFTSize;
    VectorMath::vsmul(interleavedData, 1, &scale, data, 1, m_FFTSize);
}

float* FFTFrame::realData() const
{
    return const_cast<float*>(m_realData.data());
}

float* FFTFrame::imagData() const
{
    return const_cast<float*>(m_imagData.data());
}

float* FFTFrame::getUpToDateComplexData()
{
    // FIXME: if we can't completely get rid of this method, SSE
    // optimization could be considered if it shows up hot on profiles.
    int len = m_FFTSize / 2;
    const float* real = m_realData.data();
    const float* imag = m_imagData.data();
    float* c = m_complexData.data();
    for (int i = 0; i < len; ++i) {
        int baseComplexIndex = 2 * i;
        c[baseComplexIndex] = real[i];
        c[baseComplexIndex + 1] = imag[i];
    }
    return const_cast<float*>(m_complexData.data());
}

RDFTContext* FFTFrame::contextForSize(unsigned fftSize, int trans)
{
    // FIXME: This is non-optimal. Ideally, we'd like to share the contexts for FFTFrames of the same size.
    // But FFmpeg's RDFT uses a scratch buffer inside the context and so they are not thread-safe.
    // We could improve this by sharing the FFTFrames on a per-thread basis.
    ASSERT(fftSize);
    int pow2size = static_cast<int>(log2(fftSize));
    ASSERT(pow2size < kMaxFFTPow2Size);

    RDFTContext* context = av_rdft_init(pow2size, (RDFTransformType)trans);
    return context;
}

} // namespace WebCore

#endif // USE(WEBAUDIO_FFMPEG)

#endif // ENABLE(WEB_AUDIO)
<commit_msg>Remove dead fields, found by scythe.<commit_after>/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// FFTFrame implementation using FFmpeg's RDFT algorithm,
// suitable for use on Windows and Linux.

#include "config.h"

#if ENABLE(WEB_AUDIO)

#if USE(WEBAUDIO_FFMPEG)

#include "platform/audio/FFTFrame.h"

#include "platform/audio/VectorMath.h"

extern "C" {
    #include <libavcodec/avfft.h>
}

#include "wtf/MathExtras.h"

namespace WebCore {

#if !ASSERT_DISABLED
const int kMaxFFTPow2Size = 24;
#endif

// Normal constructor: allocates for a given fftSize.
FFTFrame::FFTFrame(unsigned fftSize)
    : m_FFTSize(fftSize)
    , m_log2FFTSize(static_cast<unsigned>(log2(fftSize)))
    , m_forwardContext(0)
    , m_inverseContext(0)
    , m_complexData(fftSize)
    , m_realData(fftSize / 2)
    , m_imagData(fftSize / 2)
{
    // We only allow power of two.
    ASSERT(1UL << m_log2FFTSize == m_FFTSize);

    m_forwardContext = contextForSize(fftSize, DFT_R2C);
    m_inverseContext = contextForSize(fftSize, IDFT_C2R);
}

// Creates a blank/empty frame (interpolate() must later be called).
FFTFrame::FFTFrame()
    : m_FFTSize(0)
    , m_log2FFTSize(0)
    , m_forwardContext(0)
    , m_inverseContext(0)
{
}

// Copy constructor.
FFTFrame::FFTFrame(const FFTFrame& frame)
    : m_FFTSize(frame.m_FFTSize)
    , m_log2FFTSize(frame.m_log2FFTSize)
    , m_forwardContext(0)
    , m_inverseContext(0)
    , m_complexData(frame.m_FFTSize)
    , m_realData(frame.m_FFTSize / 2)
    , m_imagData(frame.m_FFTSize / 2)
{
    m_forwardContext = contextForSize(m_FFTSize, DFT_R2C);
    m_inverseContext = contextForSize(m_FFTSize, IDFT_C2R);

    // Copy/setup frame data.
    unsigned nbytes = sizeof(float) * (m_FFTSize / 2);
    memcpy(realData(), frame.realData(), nbytes);
    memcpy(imagData(), frame.imagData(), nbytes);
}

void FFTFrame::initialize()
{
}

void FFTFrame::cleanup()
{
}

FFTFrame::~FFTFrame()
{
    av_rdft_end(m_forwardContext);
    av_rdft_end(m_inverseContext);
}

void FFTFrame::multiply(const FFTFrame& frame)
{
    FFTFrame& frame1 = *this;
    FFTFrame& frame2 = const_cast<FFTFrame&>(frame);

    float* realP1 = frame1.realData();
    float* imagP1 = frame1.imagData();
    const float* realP2 = frame2.realData();
    const float* imagP2 = frame2.imagData();

    unsigned halfSize = fftSize() / 2;
    float real0 = realP1[0];
    float imag0 = imagP1[0];

    VectorMath::zvmul(realP1, imagP1, realP2, imagP2, realP1, imagP1, halfSize);

    // Multiply the packed DC/nyquist component
    realP1[0] = real0 * realP2[0];
    imagP1[0] = imag0 * imagP2[0];

    // Scale accounts the peculiar scaling of vecLib on the Mac.
    // This ensures the right scaling all the way back to inverse FFT.
    // FIXME: if we change the scaling on the Mac then this scale
    // factor will need to change too.
    float scale = 0.5f;

    VectorMath::vsmul(realP1, 1, &scale, realP1, 1, halfSize);
    VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, halfSize);
}

#if OS(WIN)
// On Windows, the following pragmas are equivalent to compiling the code with /fp:fast. The
// following code does not need precise FP semantics, and speed is critical here. See
// crbug.com/316740 and crrev.com/116823002.
#pragma float_control(except, off, push)
#pragma float_control(precise, off, push)
#pragma fp_contract(on)
#pragma fenv_access(off)
#endif

void FFTFrame::doFFT(const float* data)
{
    // Copy since processing is in-place.
    float* p = m_complexData.data();
    memcpy(p, data, sizeof(float) * m_FFTSize);

    // Compute Forward transform.
    av_rdft_calc(m_forwardContext, p);

    // De-interleave to separate real and complex arrays.
    int len = m_FFTSize / 2;

    // FIXME: see above comment in multiply() about scaling.
    const float scale = 2.0f;

    float* real = m_realData.data();
    float* imag = m_imagData.data();
    for (int i = 0; i < len; ++i) {
        int baseComplexIndex = 2 * i;
        // m_realData[0] is the DC component and m_imagData[0] is the nyquist component
        // since the interleaved complex data is packed.
        real[i] = scale * p[baseComplexIndex];
        imag[i] = scale * p[baseComplexIndex + 1];
    }
}

void FFTFrame::doInverseFFT(float* data)
{
    // Prepare interleaved data.
    float* interleavedData = getUpToDateComplexData();

    // Compute inverse transform.
    av_rdft_calc(m_inverseContext, interleavedData);

    // Scale so that a forward then inverse FFT yields exactly the original data.
    const float scale = 1.0 / m_FFTSize;
    VectorMath::vsmul(interleavedData, 1, &scale, data, 1, m_FFTSize);
}

float* FFTFrame::realData() const
{
    return const_cast<float*>(m_realData.data());
}

float* FFTFrame::imagData() const
{
    return const_cast<float*>(m_imagData.data());
}

float* FFTFrame::getUpToDateComplexData()
{
    // FIXME: if we can't completely get rid of this method, SSE
    // optimization could be considered if it shows up hot on profiles.
    int len = m_FFTSize / 2;
    const float* real = m_realData.data();
    const float* imag = m_imagData.data();
    float* c = m_complexData.data();
    for (int i = 0; i < len; ++i) {
        int baseComplexIndex = 2 * i;
        c[baseComplexIndex] = real[i];
        c[baseComplexIndex + 1] = imag[i];
    }
    return const_cast<float*>(m_complexData.data());
}

RDFTContext* FFTFrame::contextForSize(unsigned fftSize, int trans)
{
    // FIXME: This is non-optimal. Ideally, we'd like to share the contexts for FFTFrames of the same size.
    // But FFmpeg's RDFT uses a scratch buffer inside the context and so they are not thread-safe.
    // We could improve this by sharing the FFTFrames on a per-thread basis.
    ASSERT(fftSize);
    int pow2size = static_cast<int>(log2(fftSize));
    ASSERT(pow2size < kMaxFFTPow2Size);

    RDFTContext* context = av_rdft_init(pow2size, (RDFTransformType)trans);
    return context;
}

} // namespace WebCore

#endif // USE(WEBAUDIO_FFMPEG)

#endif // ENABLE(WEB_AUDIO)
<|endoftext|>


<commit_before>#include "TestReporterStdout.h"
#include <cstdio>

#include "TestDetails.h"

namespace UnitTest {

void TestReporterStdout::ReportFailure(TestDetails const& details, char const* failure)
{
#ifdef __APPLE__
    char const* const errorFormat = "%s:%d: error: Failure in %s: %s\n";
#else
    char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n";
#endif
    std::printf(errorFormat, details.filename, details.lineNumber, details.testName, failure);
}

void TestReporterStdout::ReportTestStart(TestDetails const& /*test*/)
{
}

void TestReporterStdout::ReportTestFinish(TestDetails const& /*test*/, float)
{
}

void TestReporterStdout::ReportSummary(int const totalTestCount, int const failedTestCount,
                                       int const failureCount, float secondsElapsed)
{
    if (failureCount > 0)
        std::printf("FAILURE: %d out of %d tests failed (%d failures).\n", failedTestCount, totalTestCount, failureCount);
    else
        std::printf("Success: %d tests passed.\n", totalTestCount);
    std::printf("Test time: %.2f seconds.\n", secondsElapsed);
}

}
<commit_msg>add __GNUG__ to the #ifdef for gcc-style output formatting.<commit_after>#include "TestReporterStdout.h"
#include <cstdio>

#include "TestDetails.h"

namespace UnitTest {

void TestReporterStdout::ReportFailure(TestDetails const& details, char const* failure)
{
#if defined(__APPLE__) || defined(__GNUG__)
    char const* const errorFormat = "%s:%d: error: Failure in %s: %s\n";
#else
    char const* const errorFormat = "%s(%d): error: Failure in %s: %s\n";
#endif
    std::printf(errorFormat, details.filename, details.lineNumber, details.testName, failure);
}

void TestReporterStdout::ReportTestStart(TestDetails const& /*test*/)
{
}

void TestReporterStdout::ReportTestFinish(TestDetails const& /*test*/, float)
{
}

void TestReporterStdout::ReportSummary(int const totalTestCount, int const failedTestCount,
                                       int const failureCount, float secondsElapsed)
{
    if (failureCount > 0)
        std::printf("FAILURE: %d out of %d tests failed (%d failures).\n", failedTestCount, totalTestCount, failureCount);
    else
        std::printf("Success: %d tests passed.\n", totalTestCount);
    std::printf("Test time: %.2f seconds.\n", secondsElapsed);
}

}
<|endoftext|>