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

#include "cling/Interpreter/InterpreterCallbacks.h"

#include "cling/Interpreter/Interpreter.h"

#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTDeserializationListener.h"

using namespace clang;

namespace cling {

  ///\brief Translates 'interesting' for the interpreter
  /// ASTDeserializationListener events into interpreter callback.
  ///
  class InterpreterPPCallbacks : public PPCallbacks {
  private:
    cling::InterpreterCallbacks* m_Callbacks;
  public:
    InterpreterPPCallbacks(InterpreterCallbacks* C) : m_Callbacks(C) { }
    ~InterpreterPPCallbacks() { }

    virtual void InclusionDirective(clang::SourceLocation HashLoc,
                                    const clang::Token &IncludeTok,
                                    llvm::StringRef FileName,
                                    bool IsAngled,
                                    clang::CharSourceRange FilenameRange,
                                    const clang::FileEntry *File,
                                    llvm::StringRef SearchPath,
                                    llvm::StringRef RelativePath,
                                    const clang::Module *Imported) {
      if (m_Callbacks) {
        m_Callbacks->InclusionDirective(HashLoc, IncludeTok, FileName,
                                        IsAngled, FilenameRange, File,
                                        SearchPath, RelativePath, Imported);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->InclusionDirective(HashLoc, IncludeTok, FileName,
                                      IsAngled, FilenameRange, File,
                                      SearchPath, RelativePath, Imported);;

      }
    }

    virtual bool FileNotFound(llvm::StringRef FileName,
                              llvm::SmallVectorImpl<char>& RecoveryPath) {
      if (m_Callbacks) {
        bool result = m_Callbacks->FileNotFound(FileName, RecoveryPath);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          result = current->FileNotFound(FileName, RecoveryPath) || result;
        return result;
      }
      // Returning true would mean that the preprocessor should try to recover.
      return false;
    }
  };

  ///\brief Translates 'interesting' for the interpreter
  /// ASTDeserializationListener events into interpreter callback.
  ///
  class InterpreterDeserializationListener : public ASTDeserializationListener {
  private:
    cling::InterpreterCallbacks* m_Callbacks;
  public:
    InterpreterDeserializationListener(InterpreterCallbacks* C)
      : m_Callbacks(C) {}

    virtual void DeclRead(serialization::DeclID, const Decl *D) {
      if (m_Callbacks) {
        m_Callbacks->DeclDeserialized(D);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->DeclDeserialized(D);
      }
    }

    virtual void TypeRead(serialization::TypeIdx, QualType T) {
      if (m_Callbacks) {
        m_Callbacks->TypeDeserialized(T.getTypePtr());
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->TypeDeserialized(T.getTypePtr());
      }
    }
  };

  ///\brief Translates 'interesting' for the interpreter ExternalSemaSource
  /// events into interpreter callbacks.
  ///
  class InterpreterExternalSemaSource : public clang::ExternalSemaSource {
  protected:
    ///\brief The interpreter callback which are subscribed for the events.
    ///
    /// Usually the callbacks is the owner of the class and the interpreter owns
    /// the callbacks so they can't be out of sync. Eg we notifying the wrong
    /// callback class.
    ///
    InterpreterCallbacks* m_Callbacks; // we don't own it.

    Sema* m_Sema; // we don't own // FIXME: once we remove ForgetSema delete.

  public:
    InterpreterExternalSemaSource(InterpreterCallbacks* C)
      : m_Callbacks(C), m_Sema(0) {}

    ~InterpreterExternalSemaSource() {
      // FIXME: Another gross hack due to the missing multiplexing AST external
      // source see Interpreter::setCallbacks.
      if (m_Sema) {
        ASTContext& C = m_Sema->getASTContext();
        // tell the owning ptr to not delete it, the callbacks will delete it.
        if (C.ExternalSource.get() == this)
          C.ExternalSource.resetWithoutRelease();
      }
    }

    virtual void InitializeSema(Sema& S) {
      m_Sema = &S;
    }

    virtual void ForgetSema() {
      m_Sema = 0;
    }

    InterpreterCallbacks* getCallbacks() const { return m_Callbacks; }

    /// \brief Provides last resort lookup for failed unqualified lookups.
    ///
    /// This gets translated into InterpreterCallback's call.
    ///
    ///\param[out] R The recovered symbol.
    ///\param[in] S The scope in which the lookup failed.
    ///
    ///\returns true if a suitable declaration is found.
    ///
    virtual bool LookupUnqualified(clang::LookupResult& R, clang::Scope* S) {
      if (m_Callbacks) {
        bool result = m_Callbacks->LookupObject(R, S);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          result = current->LookupObject(R, S) || result;
        return result;
      }

      return false;
    }

    virtual bool FindExternalVisibleDeclsByName(const clang::DeclContext* DC,
                                                clang::DeclarationName Name) {
      if (m_Callbacks) {
        bool result = m_Callbacks->LookupObject(DC, Name);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          result = current->LookupObject(DC, Name) || result;
        return result;
      }

      return false;
    }

    // Silence warning virtual function was hidden.
    using ExternalASTSource::CompleteType;
    virtual void CompleteType(TagDecl* Tag) {
      if (m_Callbacks) {
        m_Callbacks->LookupObject(Tag);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->LookupObject(Tag);
      }
    }

    void UpdateWithNewDeclsFwd(const DeclContext *DC, DeclarationName Name,
                               llvm::ArrayRef<NamedDecl*> Decls) {
      SetExternalVisibleDeclsForName(DC, Name, Decls);
    }
  };

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                                            InterpreterExternalSemaSource* IESS,
                                        InterpreterDeserializationListener* IDL,
                                             InterpreterPPCallbacks* IPPC)
    : m_Interpreter(interp),  m_ExternalSemaSource(IESS),
      m_DeserializationListener(IDL), m_IsRuntime(false), m_Next(0) {
    if (IESS)
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager().get();
    if (IDL && Reader)
      Reader->setDeserializationListener(IDL);
    if (IPPC)
      m_Interpreter->getCI()->getPreprocessor().addPPCallbacks(IPPC);
  }

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                             bool enableExternalSemaSourceCallbacks/* = false*/,
                        bool enableDeserializationListenerCallbacks/* = false*/,
                                             bool enablePPCallbacks/* = false*/)
    : m_Interpreter(interp), m_IsRuntime(false), m_Next(0) {
    if (enableExternalSemaSourceCallbacks) {
      m_ExternalSemaSource.reset(new InterpreterExternalSemaSource(this));
      m_ExternalSemaSource->InitializeSema(interp->getSema());
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    }

    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager().get();
    if (enableDeserializationListenerCallbacks && Reader) {
      // FIXME: need to create a multiplexer if a DeserializationListener is
      // alreday present.
      m_DeserializationListener.
        reset(new InterpreterDeserializationListener(this));
      Reader->setDeserializationListener(m_DeserializationListener.get());
    }

    if (enablePPCallbacks) {
      m_PPCallbacks = new InterpreterPPCallbacks(this);
      Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
      PP.addPPCallbacks(m_PPCallbacks);
    }
  }

  // pin the vtable here
  InterpreterCallbacks::~InterpreterCallbacks() {
    // FIXME: we have to remove the external source at destruction time. Needs
    // further tweaks of the patch in clang. This will be done later once the
    // patch is in clang's mainline.
  }

  void InterpreterCallbacks::SetIsRuntime(bool val) {
    m_IsRuntime = val;
    InterpreterCallbacks* current = this;
    while ((current = current->getNext()))
      current->m_IsRuntime = val;
  }

  ExternalSemaSource*
  InterpreterCallbacks::getInterpreterExternalSemaSource() const {
    return m_ExternalSemaSource.get();
  }

  ASTDeserializationListener*
  InterpreterCallbacks::getInterpreterDeserializationListener() const {
    return m_DeserializationListener.get();
  }

  bool InterpreterCallbacks::FileNotFound(llvm::StringRef FileName,
                                    llvm::SmallVectorImpl<char>& RecoveryPath) {
    // Default implementation is no op.
    return false;
  }

  bool InterpreterCallbacks::LookupObject(LookupResult&, Scope*) {
    // Default implementation is no op.
    return false;
  }

  bool InterpreterCallbacks::LookupObject(const DeclContext*, DeclarationName) {
    // Default implementation is no op.
    return false;
  }

  bool InterpreterCallbacks::LookupObject(TagDecl*) {
    // Default implementation is no op.
    return false;
  }

  void InterpreterCallbacks::UpdateWithNewDecls(const DeclContext *DC,
                                                DeclarationName Name,
                                             llvm::ArrayRef<NamedDecl*> Decls) {
    if (m_ExternalSemaSource)
      m_ExternalSemaSource->UpdateWithNewDeclsFwd(DC, Name, Decls);
  }
} // end namespace cling

// TODO: Make the build system in the testsuite aware how to build that class
// and extract it out there again.
#include "DynamicLookup.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
namespace cling {
namespace test {
  TestProxy* Tester = 0;

  extern "C" int printf(const char* fmt, ...);
  TestProxy::TestProxy(){}
  int TestProxy::Draw(){ return 12; }
  const char* TestProxy::getVersion(){ return "Interpreter.cpp"; }

  int TestProxy::Add10(int num) { return num + 10;}

  int TestProxy::Add(int a, int b) {
    return a + b;
  }

  void TestProxy::PrintString(std::string s) { printf("%s\n", s.c_str()); }

  bool TestProxy::PrintArray(int a[], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      printf("%i", a[i]);

    printf("%s", "\n");

    return true;
  }

  void TestProxy::PrintArray(float a[][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 5; ++j)
        printf("%i", (int)a[i][j]);

    printf("%s", "\n");
  }

  void TestProxy::PrintArray(int a[][4][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 4; ++j)
        for (unsigned k = 0; k < 5; ++k)
          printf("%i", a[i][j][k]);

    printf("%s", "\n");
  }

  SymbolResolverCallback::SymbolResolverCallback(Interpreter* interp)
    : InterpreterCallbacks(interp),
      m_TesterDecl(0) {
    m_Interpreter->process("cling::test::Tester = new cling::test::TestProxy();");
  }

  SymbolResolverCallback::~SymbolResolverCallback() { }

  bool SymbolResolverCallback::LookupObject(LookupResult& R, Scope* S) {
    if (m_IsRuntime) {
      // Only for demo resolve all unknown objects to cling::test::Tester
      if (!m_TesterDecl) {
        clang::Sema& SemaR = m_Interpreter->getSema();
        clang::NamespaceDecl* NSD = utils::Lookup::Namespace(&SemaR, "cling");
        NSD = utils::Lookup::Namespace(&SemaR, "test", NSD);
        m_TesterDecl = utils::Lookup::Named(&SemaR, "Tester", NSD);
      }
      assert (m_TesterDecl && "Tester not found!");
      R.addDecl(m_TesterDecl);
      return true; // Tell clang to continue.
    }

    if (ShouldResolveAtRuntime(R, S)) {
      ASTContext& C = R.getSema().getASTContext();
      DeclContext* DC = 0;
      // For DeclContext-less scopes like if (dyn_expr) {}
      while (!DC) {
        DC = static_cast<DeclContext*>(S->getEntity());
        S = S->getParent();
      }
      DeclarationName Name = R.getLookupName();
      IdentifierInfo* II = Name.getAsIdentifierInfo();
      SourceLocation Loc = R.getNameLoc();
      VarDecl* Res = VarDecl::Create(C, DC, Loc, Loc, II, C.DependentTy,
                                     /*TypeSourceInfo*/0, SC_None);

      // Annotate the decl to give a hint in cling. FIXME: Current implementation
      // is a gross hack, because TClingCallbacks shouldn't know about
      // EvaluateTSynthesizer at all!
      SourceRange invalidRange;
      Res->addAttr(new (C) AnnotateAttr(invalidRange, C, "__ResolveAtRuntime", 0));
      R.addDecl(Res);
      DC->addDecl(Res);
      // Say that we can handle the situation. Clang should try to recover
      return true;
    }

    return false;
  }

  bool SymbolResolverCallback::ShouldResolveAtRuntime(LookupResult& R,
                                                      Scope* S) {

    if (R.getLookupKind() != Sema::LookupOrdinaryName)
      return false;

    if (R.isForRedeclaration())
      return false;

    if (!R.empty())
      return false;

    // FIXME: Figure out better way to handle:
    // C++ [basic.lookup.classref]p1:
    //   In a class member access expression (5.2.5), if the . or -> token is
    //   immediately followed by an identifier followed by a <, the
    //   identifier must be looked up to determine whether the < is the
    //   beginning of a template argument list (14.2) or a less-than operator.
    //   The identifier is first looked up in the class of the object
    //   expression. If the identifier is not found, it is then looked up in
    //   the context of the entire postfix-expression and shall name a class
    //   or function template.
    //
    // We want to ignore object(.|->)member<template>
    if (R.getSema().PP.LookAhead(0).getKind() == tok::less)
      // TODO: check for . or -> in the cached token stream
      return false;

    for (Scope* DepScope = S; DepScope; DepScope = DepScope->getParent()) {
      if (DeclContext* Ctx = static_cast<DeclContext*>(DepScope->getEntity())) {
        if (!Ctx->isDependentContext())
          // For now we support only the prompt.
          if (isa<FunctionDecl>(Ctx))
            return true;
      }
    }

    return false;
  }

} // end test
} // end cling
<commit_msg>Register for notifications by Sema.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/InterpreterCallbacks.h"

#include "cling/Interpreter/Interpreter.h"

#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTDeserializationListener.h"

using namespace clang;

namespace cling {

  ///\brief Translates 'interesting' for the interpreter
  /// ASTDeserializationListener events into interpreter callback.
  ///
  class InterpreterPPCallbacks : public PPCallbacks {
  private:
    cling::InterpreterCallbacks* m_Callbacks;
  public:
    InterpreterPPCallbacks(InterpreterCallbacks* C) : m_Callbacks(C) { }
    ~InterpreterPPCallbacks() { }

    virtual void InclusionDirective(clang::SourceLocation HashLoc,
                                    const clang::Token &IncludeTok,
                                    llvm::StringRef FileName,
                                    bool IsAngled,
                                    clang::CharSourceRange FilenameRange,
                                    const clang::FileEntry *File,
                                    llvm::StringRef SearchPath,
                                    llvm::StringRef RelativePath,
                                    const clang::Module *Imported) {
      if (m_Callbacks) {
        m_Callbacks->InclusionDirective(HashLoc, IncludeTok, FileName,
                                        IsAngled, FilenameRange, File,
                                        SearchPath, RelativePath, Imported);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->InclusionDirective(HashLoc, IncludeTok, FileName,
                                      IsAngled, FilenameRange, File,
                                      SearchPath, RelativePath, Imported);;

      }
    }

    virtual bool FileNotFound(llvm::StringRef FileName,
                              llvm::SmallVectorImpl<char>& RecoveryPath) {
      if (m_Callbacks) {
        bool result = m_Callbacks->FileNotFound(FileName, RecoveryPath);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          result = current->FileNotFound(FileName, RecoveryPath) || result;
        return result;
      }
      // Returning true would mean that the preprocessor should try to recover.
      return false;
    }
  };

  ///\brief Translates 'interesting' for the interpreter
  /// ASTDeserializationListener events into interpreter callback.
  ///
  class InterpreterDeserializationListener : public ASTDeserializationListener {
  private:
    cling::InterpreterCallbacks* m_Callbacks;
  public:
    InterpreterDeserializationListener(InterpreterCallbacks* C)
      : m_Callbacks(C) {}

    virtual void DeclRead(serialization::DeclID, const Decl *D) {
      if (m_Callbacks) {
        m_Callbacks->DeclDeserialized(D);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->DeclDeserialized(D);
      }
    }

    virtual void TypeRead(serialization::TypeIdx, QualType T) {
      if (m_Callbacks) {
        m_Callbacks->TypeDeserialized(T.getTypePtr());
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->TypeDeserialized(T.getTypePtr());
      }
    }
  };

  ///\brief Translates 'interesting' for the interpreter ExternalSemaSource
  /// events into interpreter callbacks.
  ///
  class InterpreterExternalSemaSource : public clang::ExternalSemaSource {
  protected:
    ///\brief The interpreter callback which are subscribed for the events.
    ///
    /// Usually the callbacks is the owner of the class and the interpreter owns
    /// the callbacks so they can't be out of sync. Eg we notifying the wrong
    /// callback class.
    ///
    InterpreterCallbacks* m_Callbacks; // we don't own it.

    Sema* m_Sema; // we don't own // FIXME: once we remove ForgetSema delete.

  public:
    InterpreterExternalSemaSource(InterpreterCallbacks* C)
      : m_Callbacks(C), m_Sema(0) {}

    ~InterpreterExternalSemaSource() {
      // FIXME: Another gross hack due to the missing multiplexing AST external
      // source see Interpreter::setCallbacks.
      if (m_Sema) {
        ASTContext& C = m_Sema->getASTContext();
        // tell the owning ptr to not delete it, the callbacks will delete it.
        if (C.ExternalSource.get() == this)
          C.ExternalSource.resetWithoutRelease();
      }
    }

    virtual void InitializeSema(Sema& S) {
      m_Sema = &S;
    }

    virtual void ForgetSema() {
      m_Sema = 0;
    }

    InterpreterCallbacks* getCallbacks() const { return m_Callbacks; }

    /// \brief Provides last resort lookup for failed unqualified lookups.
    ///
    /// This gets translated into InterpreterCallback's call.
    ///
    ///\param[out] R The recovered symbol.
    ///\param[in] S The scope in which the lookup failed.
    ///
    ///\returns true if a suitable declaration is found.
    ///
    virtual bool LookupUnqualified(clang::LookupResult& R, clang::Scope* S) {
      if (m_Callbacks) {
        bool result = m_Callbacks->LookupObject(R, S);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          result = current->LookupObject(R, S) || result;
        return result;
      }

      return false;
    }

    virtual bool FindExternalVisibleDeclsByName(const clang::DeclContext* DC,
                                                clang::DeclarationName Name) {
      if (m_Callbacks) {
        bool result = m_Callbacks->LookupObject(DC, Name);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          result = current->LookupObject(DC, Name) || result;
        return result;
      }

      return false;
    }

    // Silence warning virtual function was hidden.
    using ExternalASTSource::CompleteType;
    virtual void CompleteType(TagDecl* Tag) {
      if (m_Callbacks) {
        m_Callbacks->LookupObject(Tag);
        InterpreterCallbacks* current = m_Callbacks;
        while ((current = current->getNext()))
          current->LookupObject(Tag);
      }
    }

    void UpdateWithNewDeclsFwd(const DeclContext *DC, DeclarationName Name,
                               llvm::ArrayRef<NamedDecl*> Decls) {
      SetExternalVisibleDeclsForName(DC, Name, Decls);
    }
  };

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                                            InterpreterExternalSemaSource* IESS,
                                        InterpreterDeserializationListener* IDL,
                                             InterpreterPPCallbacks* IPPC)
    : m_Interpreter(interp),  m_ExternalSemaSource(IESS),
      m_DeserializationListener(IDL), m_IsRuntime(false), m_Next(0) {
    if (IESS)
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager().get();
    if (IDL && Reader)
      Reader->setDeserializationListener(IDL);
    if (IPPC)
      m_Interpreter->getCI()->getPreprocessor().addPPCallbacks(IPPC);
  }

  InterpreterCallbacks::InterpreterCallbacks(Interpreter* interp,
                             bool enableExternalSemaSourceCallbacks/* = false*/,
                        bool enableDeserializationListenerCallbacks/* = false*/,
                                             bool enablePPCallbacks/* = false*/)
    : m_Interpreter(interp), m_IsRuntime(false), m_Next(0) {
    if (enableExternalSemaSourceCallbacks) {
      m_ExternalSemaSource.reset(new InterpreterExternalSemaSource(this));
      m_ExternalSemaSource->InitializeSema(interp->getSema());
      m_Interpreter->getSema().addExternalSource(m_ExternalSemaSource.get());
    }

    ASTReader* Reader = m_Interpreter->getCI()->getModuleManager().get();
    if (enableDeserializationListenerCallbacks && Reader) {
      // FIXME: need to create a multiplexer if a DeserializationListener is
      // alreday present.
      m_DeserializationListener.
        reset(new InterpreterDeserializationListener(this));
      Reader->setDeserializationListener(m_DeserializationListener.get());
    }

    if (enablePPCallbacks) {
      m_PPCallbacks = new InterpreterPPCallbacks(this);
      Preprocessor& PP = m_Interpreter->getCI()->getPreprocessor();
      PP.addPPCallbacks(m_PPCallbacks);
    }
  }

  // pin the vtable here
  InterpreterCallbacks::~InterpreterCallbacks() {
    // FIXME: we have to remove the external source at destruction time. Needs
    // further tweaks of the patch in clang. This will be done later once the
    // patch is in clang's mainline.
  }

  void InterpreterCallbacks::SetIsRuntime(bool val) {
    m_IsRuntime = val;
    InterpreterCallbacks* current = this;
    while ((current = current->getNext()))
      current->m_IsRuntime = val;
  }

  ExternalSemaSource*
  InterpreterCallbacks::getInterpreterExternalSemaSource() const {
    return m_ExternalSemaSource.get();
  }

  ASTDeserializationListener*
  InterpreterCallbacks::getInterpreterDeserializationListener() const {
    return m_DeserializationListener.get();
  }

  bool InterpreterCallbacks::FileNotFound(llvm::StringRef FileName,
                                    llvm::SmallVectorImpl<char>& RecoveryPath) {
    // Default implementation is no op.
    return false;
  }

  bool InterpreterCallbacks::LookupObject(LookupResult&, Scope*) {
    // Default implementation is no op.
    return false;
  }

  bool InterpreterCallbacks::LookupObject(const DeclContext*, DeclarationName) {
    // Default implementation is no op.
    return false;
  }

  bool InterpreterCallbacks::LookupObject(TagDecl*) {
    // Default implementation is no op.
    return false;
  }

  void InterpreterCallbacks::UpdateWithNewDecls(const DeclContext *DC,
                                                DeclarationName Name,
                                             llvm::ArrayRef<NamedDecl*> Decls) {
    if (m_ExternalSemaSource)
      m_ExternalSemaSource->UpdateWithNewDeclsFwd(DC, Name, Decls);
  }
} // end namespace cling

// TODO: Make the build system in the testsuite aware how to build that class
// and extract it out there again.
#include "DynamicLookup.h"
#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
namespace cling {
namespace test {
  TestProxy* Tester = 0;

  extern "C" int printf(const char* fmt, ...);
  TestProxy::TestProxy(){}
  int TestProxy::Draw(){ return 12; }
  const char* TestProxy::getVersion(){ return "Interpreter.cpp"; }

  int TestProxy::Add10(int num) { return num + 10;}

  int TestProxy::Add(int a, int b) {
    return a + b;
  }

  void TestProxy::PrintString(std::string s) { printf("%s\n", s.c_str()); }

  bool TestProxy::PrintArray(int a[], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      printf("%i", a[i]);

    printf("%s", "\n");

    return true;
  }

  void TestProxy::PrintArray(float a[][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 5; ++j)
        printf("%i", (int)a[i][j]);

    printf("%s", "\n");
  }

  void TestProxy::PrintArray(int a[][4][5], size_t size) {
    for (unsigned i = 0; i < size; ++i)
      for (unsigned j = 0; j < 4; ++j)
        for (unsigned k = 0; k < 5; ++k)
          printf("%i", a[i][j][k]);

    printf("%s", "\n");
  }

  SymbolResolverCallback::SymbolResolverCallback(Interpreter* interp)
    : InterpreterCallbacks(interp, /*EnableSemaCB*/true),
      m_TesterDecl(0) {
    m_Interpreter->process("cling::test::Tester = new cling::test::TestProxy();");
  }

  SymbolResolverCallback::~SymbolResolverCallback() { }

  bool SymbolResolverCallback::LookupObject(LookupResult& R, Scope* S) {
    if (m_IsRuntime) {
      // Only for demo resolve all unknown objects to cling::test::Tester
      if (!m_TesterDecl) {
        clang::Sema& SemaR = m_Interpreter->getSema();
        clang::NamespaceDecl* NSD = utils::Lookup::Namespace(&SemaR, "cling");
        NSD = utils::Lookup::Namespace(&SemaR, "test", NSD);
        m_TesterDecl = utils::Lookup::Named(&SemaR, "Tester", NSD);
      }
      assert (m_TesterDecl && "Tester not found!");
      R.addDecl(m_TesterDecl);
      return true; // Tell clang to continue.
    }

    if (ShouldResolveAtRuntime(R, S)) {
      ASTContext& C = R.getSema().getASTContext();
      DeclContext* DC = 0;
      // For DeclContext-less scopes like if (dyn_expr) {}
      while (!DC) {
        DC = static_cast<DeclContext*>(S->getEntity());
        S = S->getParent();
      }
      DeclarationName Name = R.getLookupName();
      IdentifierInfo* II = Name.getAsIdentifierInfo();
      SourceLocation Loc = R.getNameLoc();
      VarDecl* Res = VarDecl::Create(C, DC, Loc, Loc, II, C.DependentTy,
                                     /*TypeSourceInfo*/0, SC_None);

      // Annotate the decl to give a hint in cling. FIXME: Current implementation
      // is a gross hack, because TClingCallbacks shouldn't know about
      // EvaluateTSynthesizer at all!
      SourceRange invalidRange;
      Res->addAttr(new (C) AnnotateAttr(invalidRange, C, "__ResolveAtRuntime", 0));
      R.addDecl(Res);
      DC->addDecl(Res);
      // Say that we can handle the situation. Clang should try to recover
      return true;
    }

    return false;
  }

  bool SymbolResolverCallback::ShouldResolveAtRuntime(LookupResult& R,
                                                      Scope* S) {

    if (R.getLookupKind() != Sema::LookupOrdinaryName)
      return false;

    if (R.isForRedeclaration())
      return false;

    if (!R.empty())
      return false;

    // FIXME: Figure out better way to handle:
    // C++ [basic.lookup.classref]p1:
    //   In a class member access expression (5.2.5), if the . or -> token is
    //   immediately followed by an identifier followed by a <, the
    //   identifier must be looked up to determine whether the < is the
    //   beginning of a template argument list (14.2) or a less-than operator.
    //   The identifier is first looked up in the class of the object
    //   expression. If the identifier is not found, it is then looked up in
    //   the context of the entire postfix-expression and shall name a class
    //   or function template.
    //
    // We want to ignore object(.|->)member<template>
    if (R.getSema().PP.LookAhead(0).getKind() == tok::less)
      // TODO: check for . or -> in the cached token stream
      return false;

    for (Scope* DepScope = S; DepScope; DepScope = DepScope->getParent()) {
      if (DeclContext* Ctx = static_cast<DeclContext*>(DepScope->getEntity())) {
        if (!Ctx->isDependentContext())
          // For now we support only the prompt.
          if (isa<FunctionDecl>(Ctx))
            return true;
      }
    }

    return false;
  }

} // end test
} // end cling
<|endoftext|>


<commit_before>#include <unordered_set>
#include <boost/format.hpp>
#include <r3/path/GeometricPath.h>

using boost::format;
using boost::str;
using dart::dynamics::DegreeOfFreedomPtr;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using r3::path::GeometricPath;

/*
 * GeometricPath::Waypoint
 */
std::vector<DegreeOfFreedomPtr> const &GeometricPath::Waypoint::dofs() const
{
  return path_->dofs_;
}

Eigen::VectorXd GeometricPath::Waypoint::positions() const
{
  return path_->waypoints_.row(index_);
}

GeometricPath::Waypoint::Waypoint(GeometricPath const *path, size_t index)
  : path_(path)
  , index_(index)
{
}

/*
 * GeometricPath
 */
GeometricPath::GeometricPath(
    std::vector<DegreeOfFreedomPtr> const &dofs, MatrixXd const &waypoints)
  : dofs_(dofs)
  , waypoints_(waypoints)
{
  using dart::dynamics::DegreeOfFreedom;

  if (waypoints_.cols() != dofs_.size()) {
    throw std::runtime_error(str(
      format("Waypoints have incorrect DOF; expected %d, got %d.")
        % dofs_.size() % waypoints_.cols()));
  }

  std::unordered_set<DegreeOfFreedom const *> unique_dofs;
  for (DegreeOfFreedomPtr const &dof : dofs_) {
    DegreeOfFreedom const *dof_ptr = dof.get();

    if (!dof_ptr) {
      throw std::runtime_error("Path contains NULL DegreeOfFreedom.");
    } else if (unique_dofs.count(dof_ptr)) {
      throw std::runtime_error(str(
        format("Path contains duplicate DOF '%s'.") % dof->getName()));
    }
    unique_dofs.insert(dof_ptr);
  }
}

bool GeometricPath::is_valid() const
{
  for (DegreeOfFreedomPtr const &dof : dofs_) {
    if (!dof) {
      return false;
    }
  }
  return true;
}

size_t GeometricPath::num_dofs() const
{
  return waypoints_.cols();
}

size_t GeometricPath::num_waypoints() const
{
  return waypoints_.rows();
}

double GeometricPath::arc_length() const
{
  double arclength = 0.;

  for (size_t iwaypoint = 1; iwaypoint < waypoints_.size(); ++iwaypoint) {
    VectorXd const &waypoint1 = waypoints_.row(iwaypoint - 1);
    VectorXd const &waypoint2 = waypoints_.row(iwaypoint);
    arclength += (waypoint2 - waypoint1).norm();
  }

  return arclength;
}

std::vector<DegreeOfFreedomPtr> const &GeometricPath::dofs() const
{
  return dofs_;
}

Eigen::MatrixXd &GeometricPath::matrix()
{
  return waypoints_;
}

Eigen::MatrixXd const &GeometricPath::matrix() const
{
  return waypoints_;
}

auto GeometricPath::getWaypoint(size_t i) const -> Waypoint
{
  if (i < num_waypoints()) {
    return Waypoint(this, i);
  } else {
    throw std::runtime_error(str(
      format("Waypoint index is out of range; %d > %d.")
        % i % (num_waypoints() - 1)));
  }
}

<commit_msg>Removed dead code.<commit_after><|endoftext|>


<commit_before>//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the MSP430 target.
//
//===----------------------------------------------------------------------===//

#include "MSP430.h"
#include "MSP430ISelLowering.h"
#include "MSP430TargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include <queue>
#include <set>
using namespace llvm;

/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
/// instructions for SelectionDAG operations.
///
namespace {
  class MSP430DAGToDAGISel : public SelectionDAGISel {
    MSP430TargetLowering &Lowering;
    const MSP430Subtarget &Subtarget;

  public:
    MSP430DAGToDAGISel(MSP430TargetMachine &TM)
      : SelectionDAGISel(TM),
        Lowering(*TM.getTargetLowering()),
        Subtarget(*TM.getSubtargetImpl()) { }

    virtual void InstructionSelect();

    virtual const char *getPassName() const {
      return "MSP430 DAG->DAG Pattern Instruction Selection";
    }

    // Include the pieces autogenerated from the target description.
  #include "MSP430GenDAGISel.inc"

  private:
    SDNode *Select(SDValue Op);
    bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Disp, SDValue &Base);

  #ifndef NDEBUG
    unsigned Indent;
  #endif
  };
}  // end anonymous namespace

/// createMSP430ISelDag - This pass converts a legalized DAG into a
/// MSP430-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM) {
  return new MSP430DAGToDAGISel(TM);
}

bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr,
                                    SDValue &Disp, SDValue &Base) {
  // We don't support frame index stuff yet.
  if (isa<FrameIndexSDNode>(Addr))
    return false;

  // Operand is a result from ADD with constant operand which fits into i16.
  if (Addr.getOpcode() == ISD::ADD) {
    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
      uint64_t CVal = CN->getZExtValue();
      // Offset should fit into 16 bits.
      if (((CVal << 48) >> 48) == CVal) {
        // We don't support frame index stuff yet.
        if (isa<FrameIndexSDNode>(Addr.getOperand(0)))
          return false;

        Base = Addr.getOperand(0);
        Disp = CurDAG->getTargetConstant(CVal, MVT::i16);

        return true;
      }
    }
  }

  Base = Addr;
  Disp = CurDAG->getTargetConstant(0, MVT::i16);

  return true;
}

/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MSP430DAGToDAGISel::InstructionSelect() {
  DEBUG(BB->dump());

  // Select target instructions for the DAG.
  SelectRoot(*CurDAG);

  CurDAG->RemoveDeadNodes();
}

SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
  SDNode *Node = Op.getNode();

  // Dump information about the Node being selected
  #ifndef NDEBUG
  DOUT << std::string(Indent, ' ') << "Selecting: ";
  DEBUG(Node->dump(CurDAG));
  DOUT << "\n";
  Indent += 2;
  #endif

  // If we have a custom node, we already have selected!
  if (Node->isMachineOpcode()) {
    #ifndef NDEBUG
    DOUT << std::string(Indent-2, ' ') << "== ";
    DEBUG(Node->dump(CurDAG));
    DOUT << "\n";
    Indent -= 2;
    #endif
    return NULL;
  }

  // Instruction Selection not handled by the auto-generated tablegen selection
  // should be handled here.
  // Something like this:
  //   unsigned Opcode = Node->getOpcode();
  //   switch (Opcode) {
  //   default: break;
  //   case ISD::Foo:
  //    return SelectFoo(Node)
  //  }

  // Select the default instruction
  SDNode *ResNode = SelectCode(Op);

  #ifndef NDEBUG
  DOUT << std::string(Indent-2, ' ') << "=> ";
  if (ResNode == NULL || ResNode == Op.getNode())
    DEBUG(Op.getNode()->dump(CurDAG));
  else
    DEBUG(ResNode->dump(CurDAG));
  DOUT << "\n";
  Indent -= 2;
  #endif

  return ResNode;
}
<commit_msg>Match wrapper node for address<commit_after>//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines an instruction selector for the MSP430 target.
//
//===----------------------------------------------------------------------===//

#include "MSP430.h"
#include "MSP430ISelLowering.h"
#include "MSP430TargetMachine.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include <queue>
#include <set>
using namespace llvm;

/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
/// instructions for SelectionDAG operations.
///
namespace {
  class MSP430DAGToDAGISel : public SelectionDAGISel {
    MSP430TargetLowering &Lowering;
    const MSP430Subtarget &Subtarget;

  public:
    MSP430DAGToDAGISel(MSP430TargetMachine &TM)
      : SelectionDAGISel(TM),
        Lowering(*TM.getTargetLowering()),
        Subtarget(*TM.getSubtargetImpl()) { }

    virtual void InstructionSelect();

    virtual const char *getPassName() const {
      return "MSP430 DAG->DAG Pattern Instruction Selection";
    }

    // Include the pieces autogenerated from the target description.
  #include "MSP430GenDAGISel.inc"

  private:
    SDNode *Select(SDValue Op);
    bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Disp, SDValue &Base);

  #ifndef NDEBUG
    unsigned Indent;
  #endif
  };
}  // end anonymous namespace

/// createMSP430ISelDag - This pass converts a legalized DAG into a
/// MSP430-specific DAG, ready for instruction scheduling.
///
FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM) {
  return new MSP430DAGToDAGISel(TM);
}

bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr,
                                    SDValue &Disp, SDValue &Base) {
  // We don't support frame index stuff yet.
  if (isa<FrameIndexSDNode>(Addr))
    return false;

  // Operand is a result from ADD with constant operand which fits into i16.
  switch (Addr.getOpcode()) {
  case ISD::ADD:
    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
      uint64_t CVal = CN->getZExtValue();
      // Offset should fit into 16 bits.
      if (((CVal << 48) >> 48) == CVal) {
        // We don't support frame index stuff yet.
        if (isa<FrameIndexSDNode>(Addr.getOperand(0)))
          return false;

        Base = Addr.getOperand(0);
        Disp = CurDAG->getTargetConstant(CVal, MVT::i16);

        return true;
      }
    }
    break;
  case MSP430ISD::Wrapper:
    SDValue N0 = Addr.getOperand(0);
    if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
      // We can match addresses of globals without any offsets
      if (!G->getOffset()) {
        Base = CurDAG->getTargetGlobalAddress(G->getGlobal(),
                                              MVT::i16, 0);
        Disp = CurDAG->getTargetConstant(0, MVT::i16);

        return true;
      }
    }
    break;
  };

  Base = Addr;
  Disp = CurDAG->getTargetConstant(0, MVT::i16);

  return true;
}

/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MSP430DAGToDAGISel::InstructionSelect() {
  DEBUG(BB->dump());

  // Select target instructions for the DAG.
  SelectRoot(*CurDAG);

  CurDAG->RemoveDeadNodes();
}

SDNode *MSP430DAGToDAGISel::Select(SDValue Op) {
  SDNode *Node = Op.getNode();

  // Dump information about the Node being selected
  #ifndef NDEBUG
  DOUT << std::string(Indent, ' ') << "Selecting: ";
  DEBUG(Node->dump(CurDAG));
  DOUT << "\n";
  Indent += 2;
  #endif

  // If we have a custom node, we already have selected!
  if (Node->isMachineOpcode()) {
    #ifndef NDEBUG
    DOUT << std::string(Indent-2, ' ') << "== ";
    DEBUG(Node->dump(CurDAG));
    DOUT << "\n";
    Indent -= 2;
    #endif
    return NULL;
  }

  // Instruction Selection not handled by the auto-generated tablegen selection
  // should be handled here.
  // Something like this:
  //   unsigned Opcode = Node->getOpcode();
  //   switch (Opcode) {
  //   default: break;
  //   case ISD::Foo:
  //    return SelectFoo(Node)
  //  }

  // Select the default instruction
  SDNode *ResNode = SelectCode(Op);

  #ifndef NDEBUG
  DOUT << std::string(Indent-2, ' ') << "=> ";
  if (ResNode == NULL || ResNode == Op.getNode())
    DEBUG(Op.getNode()->dump(CurDAG));
  else
    DEBUG(ResNode->dump(CurDAG));
  DOUT << "\n";
  Indent -= 2;
  #endif

  return ResNode;
}
<|endoftext|>


<commit_before>//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements IR-level optimizations of image access code,
// including:
//
// 1. Eliminate istypep intrinsics when image access qualifier is known
//
//===----------------------------------------------------------------------===//

#include "NVPTX.h"
#include "NVPTXUtilities.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"

using namespace llvm;

namespace {
class NVPTXImageOptimizer : public FunctionPass {
private:
  static char ID;
  SmallVector<Instruction*, 4> InstrToDelete;

public:
  NVPTXImageOptimizer();

  bool runOnFunction(Function &F) override;

private:
  bool replaceIsTypePSampler(Instruction &I);
  bool replaceIsTypePSurface(Instruction &I);
  bool replaceIsTypePTexture(Instruction &I);
  Value *cleanupValue(Value *V);
  void replaceWith(Instruction *From, ConstantInt *To);
};
}

char NVPTXImageOptimizer::ID = 0;

NVPTXImageOptimizer::NVPTXImageOptimizer()
  : FunctionPass(ID) {}

bool NVPTXImageOptimizer::runOnFunction(Function &F) {
  if (skipFunction(F))
    return false;

  bool Changed = false;
  InstrToDelete.clear();

  // Look for call instructions in the function
  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;
       ++BI) {
    for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
         I != E; ++I) {
      Instruction &Instr = *I;
      if (CallInst *CI = dyn_cast<CallInst>(I)) {
        Function *CalledF = CI->getCalledFunction();
        if (CalledF && CalledF->isIntrinsic()) {
          // This is an intrinsic function call, check if its an istypep
          switch (CalledF->getIntrinsicID()) {
          default: break;
          case Intrinsic::nvvm_istypep_sampler:
            Changed |= replaceIsTypePSampler(Instr);
            break;
          case Intrinsic::nvvm_istypep_surface:
            Changed |= replaceIsTypePSurface(Instr);
            break;
          case Intrinsic::nvvm_istypep_texture:
            Changed |= replaceIsTypePTexture(Instr);
            break;
          }
        }
      }
    }
  }

  // Delete any istypep instances we replaced in the IR
  for (unsigned i = 0, e = InstrToDelete.size(); i != e; ++i)
    InstrToDelete[i]->eraseFromParent();

  return Changed;
}

bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {
  Value *TexHandle = cleanupValue(I.getOperand(0));
  if (isSampler(*TexHandle)) {
    // This is an OpenCL sampler, so it must be a samplerref
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
    return true;
  } else if (isImageWriteOnly(*TexHandle) ||
             isImageReadWrite(*TexHandle) ||
             isImageReadOnly(*TexHandle)) {
    // This is an OpenCL image, so it cannot be a samplerref
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
    return true;
  } else {
    // The image type is unknown, so we cannot eliminate the intrinsic
    return false;
  }
}

bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
  Value *TexHandle = cleanupValue(I.getOperand(0));
  if (isImageReadWrite(*TexHandle) ||
      isImageWriteOnly(*TexHandle)) {
    // This is an OpenCL read-only/read-write image, so it must be a surfref
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
    return true;
  } else if (isImageReadOnly(*TexHandle) ||
             isSampler(*TexHandle)) {
    // This is an OpenCL read-only/ imageor sampler, so it cannot be
    // a surfref
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
    return true;
  } else {
    // The image type is unknown, so we cannot eliminate the intrinsic
    return false;
  }
}

bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
  Value *TexHandle = cleanupValue(I.getOperand(0));
  if (isImageReadOnly(*TexHandle)) {
    // This is an OpenCL read-only image, so it must be a texref
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
    return true;
  } else if (isImageWriteOnly(*TexHandle) ||
             isImageReadWrite(*TexHandle) ||
             isSampler(*TexHandle)) {
    // This is an OpenCL read-write/write-only image or a sampler, so it
    // cannot be a texref
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
    return true;
  } else {
    // The image type is unknown, so we cannot eliminate the intrinsic
    return false;
  }
}

void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
  // We implement "poor man's DCE" here to make sure any code that is no longer
  // live is actually unreachable and can be trivially eliminated by the
  // unreachable block elimination pass.
  for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end();
       UI != UE; ++UI) {
    if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) {
      if (BI->isUnconditional()) continue;
      BasicBlock *Dest;
      if (To->isZero())
        // Get false block
        Dest = BI->getSuccessor(1);
      else
        // Get true block
        Dest = BI->getSuccessor(0);
      BranchInst::Create(Dest, BI);
      InstrToDelete.push_back(BI);
    }
  }
  From->replaceAllUsesWith(To);
  InstrToDelete.push_back(From);
}

Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
  if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
    return cleanupValue(EVI->getAggregateOperand());
  }
  return V;
}

FunctionPass *llvm::createNVPTXImageOptimizerPass() {
  return new NVPTXImageOptimizer();
}
<commit_msg>[NVPTX] Remove unnecessary isImageReadoOnly(), isImageWriteOnly(), & isImageReadWrite calls<commit_after>//===-- NVPTXImageOptimizer.cpp - Image optimization pass -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass implements IR-level optimizations of image access code,
// including:
//
// 1. Eliminate istypep intrinsics when image access qualifier is known
//
//===----------------------------------------------------------------------===//

#include "NVPTX.h"
#include "NVPTXUtilities.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"

using namespace llvm;

namespace {
class NVPTXImageOptimizer : public FunctionPass {
private:
  static char ID;
  SmallVector<Instruction*, 4> InstrToDelete;

public:
  NVPTXImageOptimizer();

  bool runOnFunction(Function &F) override;

private:
  bool replaceIsTypePSampler(Instruction &I);
  bool replaceIsTypePSurface(Instruction &I);
  bool replaceIsTypePTexture(Instruction &I);
  Value *cleanupValue(Value *V);
  void replaceWith(Instruction *From, ConstantInt *To);
};
}

char NVPTXImageOptimizer::ID = 0;

NVPTXImageOptimizer::NVPTXImageOptimizer()
  : FunctionPass(ID) {}

bool NVPTXImageOptimizer::runOnFunction(Function &F) {
  if (skipFunction(F))
    return false;

  bool Changed = false;
  InstrToDelete.clear();

  // Look for call instructions in the function
  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;
       ++BI) {
    for (BasicBlock::iterator I = (*BI).begin(), E = (*BI).end();
         I != E; ++I) {
      Instruction &Instr = *I;
      if (CallInst *CI = dyn_cast<CallInst>(I)) {
        Function *CalledF = CI->getCalledFunction();
        if (CalledF && CalledF->isIntrinsic()) {
          // This is an intrinsic function call, check if its an istypep
          switch (CalledF->getIntrinsicID()) {
          default: break;
          case Intrinsic::nvvm_istypep_sampler:
            Changed |= replaceIsTypePSampler(Instr);
            break;
          case Intrinsic::nvvm_istypep_surface:
            Changed |= replaceIsTypePSurface(Instr);
            break;
          case Intrinsic::nvvm_istypep_texture:
            Changed |= replaceIsTypePTexture(Instr);
            break;
          }
        }
      }
    }
  }

  // Delete any istypep instances we replaced in the IR
  for (unsigned i = 0, e = InstrToDelete.size(); i != e; ++i)
    InstrToDelete[i]->eraseFromParent();

  return Changed;
}

bool NVPTXImageOptimizer::replaceIsTypePSampler(Instruction &I) {
  Value *TexHandle = cleanupValue(I.getOperand(0));
  if (isSampler(*TexHandle)) {
    // This is an OpenCL sampler, so it must be a samplerref
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
    return true;
  } else if (isImage(*TexHandle)) {
    // This is an OpenCL image, so it cannot be a samplerref
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
    return true;
  } else {
    // The image type is unknown, so we cannot eliminate the intrinsic
    return false;
  }
}

bool NVPTXImageOptimizer::replaceIsTypePSurface(Instruction &I) {
  Value *TexHandle = cleanupValue(I.getOperand(0));
  if (isImageReadWrite(*TexHandle) ||
      isImageWriteOnly(*TexHandle)) {
    // This is an OpenCL read-only/read-write image, so it must be a surfref
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
    return true;
  } else if (isImageReadOnly(*TexHandle) ||
             isSampler(*TexHandle)) {
    // This is an OpenCL read-only/ imageor sampler, so it cannot be
    // a surfref
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
    return true;
  } else {
    // The image type is unknown, so we cannot eliminate the intrinsic
    return false;
  }
}

bool NVPTXImageOptimizer::replaceIsTypePTexture(Instruction &I) {
  Value *TexHandle = cleanupValue(I.getOperand(0));
  if (isImageReadOnly(*TexHandle)) {
    // This is an OpenCL read-only image, so it must be a texref
    replaceWith(&I, ConstantInt::getTrue(I.getContext()));
    return true;
  } else if (isImageWriteOnly(*TexHandle) ||
             isImageReadWrite(*TexHandle) ||
             isSampler(*TexHandle)) {
    // This is an OpenCL read-write/write-only image or a sampler, so it
    // cannot be a texref
    replaceWith(&I, ConstantInt::getFalse(I.getContext()));
    return true;
  } else {
    // The image type is unknown, so we cannot eliminate the intrinsic
    return false;
  }
}

void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) {
  // We implement "poor man's DCE" here to make sure any code that is no longer
  // live is actually unreachable and can be trivially eliminated by the
  // unreachable block elimination pass.
  for (CallInst::use_iterator UI = From->use_begin(), UE = From->use_end();
       UI != UE; ++UI) {
    if (BranchInst *BI = dyn_cast<BranchInst>(*UI)) {
      if (BI->isUnconditional()) continue;
      BasicBlock *Dest;
      if (To->isZero())
        // Get false block
        Dest = BI->getSuccessor(1);
      else
        // Get true block
        Dest = BI->getSuccessor(0);
      BranchInst::Create(Dest, BI);
      InstrToDelete.push_back(BI);
    }
  }
  From->replaceAllUsesWith(To);
  InstrToDelete.push_back(From);
}

Value *NVPTXImageOptimizer::cleanupValue(Value *V) {
  if (ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(V)) {
    return cleanupValue(EVI->getAggregateOperand());
  }
  return V;
}

FunctionPass *llvm::createNVPTXImageOptimizerPass() {
  return new NVPTXImageOptimizer();
}
<|endoftext|>


<commit_before>//===-- PowerPCBranchSelector.cpp - Emit long conditional branches-*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Baegeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that scans a machine function to determine which
// conditional branches need more than 16 bits of displacement to reach their
// target basic block.  It does this in two passes; a calculation of basic block
// positions pass, and a branch psuedo op to machine branch opcode pass.  This
// pass should be run last, just before the assembly printer.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "bsel"
#include "PowerPC.h"
#include "PowerPCInstrBuilder.h"
#include "PowerPCInstrInfo.h"
#include "PPC32InstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Support/Debug.h"
#include <map>
using namespace llvm;

namespace {
  struct BSel : public MachineFunctionPass {
    // OffsetMap - Mapping between BB and byte offset from start of function
    std::map<MachineBasicBlock*, unsigned> OffsetMap;

    /// bytesForOpcode - A convenience function for totalling up the number of
    /// bytes in a basic block.
    ///
    static unsigned bytesForOpcode(unsigned opcode) {
      switch (opcode) {
      case PPC::COND_BRANCH:
        // while this will be 4 most of the time, if we emit 12 it is just a
        // minor pessimization that saves us from having to worry about
        // keeping the offsets up to date later when we emit long branch glue.
        return 12;
      case PPC::IMPLICIT_DEF: // no asm emitted
        return 0;
        break;
      default:
        return 4; // PowerPC instructions are all 4 bytes
        break;
      }
    }

    virtual bool runOnMachineFunction(MachineFunction &Fn) {
      // Running total of instructions encountered since beginning of function
      unsigned ByteCount = 0;

      // For each MBB, add its offset to the offset map, and count up its
      // instructions
      for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
           ++MFI) {
        MachineBasicBlock *MBB = MFI;
        OffsetMap[MBB] = ByteCount;

        for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
             MBBI != EE; ++MBBI)
          ByteCount += bytesForOpcode(MBBI->getOpcode());
      }

      // We're about to run over the MBB's again, so reset the ByteCount
      ByteCount = 0;

      // For each MBB, find the conditional branch pseudo instructions, and
      // calculate the difference between the target MBB and the current ICount
      // to decide whether or not to emit a short or long branch.
      //
      // short branch:
      // bCC .L_TARGET_MBB
      //
      // long branch:
      // bInverseCC $PC+8
      // b .L_TARGET_MBB
      // b .L_FALLTHROUGH_MBB

      for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
           ++MFI) {
        MachineBasicBlock *MBB = MFI;

        for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
             MBBI != EE; ++MBBI) {
          if (MBBI->getOpcode() == PPC::COND_BRANCH) {
            // condbranch operands:
            // 0. CR0 register
            // 1. bc opcode
            // 2. target MBB
            // 3. fallthrough MBB
            MachineBasicBlock *trueMBB =
              MBBI->getOperand(2).getMachineBasicBlock();
            MachineBasicBlock *falseMBB =
              MBBI->getOperand(3).getMachineBasicBlock();

            int Displacement = OffsetMap[trueMBB] - ByteCount;
            unsigned Opcode = MBBI->getOperand(1).getImmedValue();
            unsigned Inverted = PPC32InstrInfo::invertPPCBranchOpcode(Opcode);

            MachineInstr *MI = MBBI;
            if (Displacement >= -32768 && Displacement <= 32767) {
              BuildMI(*MBB, MBBI, Opcode, 2).addReg(PPC::CR0).addMBB(trueMBB);
            } else {
              BuildMI(*MBB, MBBI, Inverted, 2).addReg(PPC::CR0).addSImm(8);
              BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(trueMBB);
              BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(falseMBB);
            }
            MBB->erase(MI);
          }
          ByteCount += bytesForOpcode(MBBI->getOpcode());
        }
      }

      OffsetMap.clear();
      return true;
    }

    virtual const char *getPassName() const {
      return "PowerPC Branch Selection";
    }
  };
}

/// createPPCBranchSelectionPass - returns an instance of the Branch Selection
/// Pass
///
FunctionPass *llvm::createPPCBranchSelectionPass() {
  return new BSel();
}
<commit_msg>Remove unnecessary header include<commit_after>//===-- PowerPCBranchSelector.cpp - Emit long conditional branches-*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Baegeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that scans a machine function to determine which
// conditional branches need more than 16 bits of displacement to reach their
// target basic block.  It does this in two passes; a calculation of basic block
// positions pass, and a branch psuedo op to machine branch opcode pass.  This
// pass should be run last, just before the assembly printer.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "bsel"
#include "PowerPC.h"
#include "PowerPCInstrBuilder.h"
#include "PowerPCInstrInfo.h"
#include "PPC32InstrInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/Debug.h"
#include <map>
using namespace llvm;

namespace {
  struct BSel : public MachineFunctionPass {
    // OffsetMap - Mapping between BB and byte offset from start of function
    std::map<MachineBasicBlock*, unsigned> OffsetMap;

    /// bytesForOpcode - A convenience function for totalling up the number of
    /// bytes in a basic block.
    ///
    static unsigned bytesForOpcode(unsigned opcode) {
      switch (opcode) {
      case PPC::COND_BRANCH:
        // while this will be 4 most of the time, if we emit 12 it is just a
        // minor pessimization that saves us from having to worry about
        // keeping the offsets up to date later when we emit long branch glue.
        return 12;
      case PPC::IMPLICIT_DEF: // no asm emitted
        return 0;
        break;
      default:
        return 4; // PowerPC instructions are all 4 bytes
        break;
      }
    }

    virtual bool runOnMachineFunction(MachineFunction &Fn) {
      // Running total of instructions encountered since beginning of function
      unsigned ByteCount = 0;

      // For each MBB, add its offset to the offset map, and count up its
      // instructions
      for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
           ++MFI) {
        MachineBasicBlock *MBB = MFI;
        OffsetMap[MBB] = ByteCount;

        for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
             MBBI != EE; ++MBBI)
          ByteCount += bytesForOpcode(MBBI->getOpcode());
      }

      // We're about to run over the MBB's again, so reset the ByteCount
      ByteCount = 0;

      // For each MBB, find the conditional branch pseudo instructions, and
      // calculate the difference between the target MBB and the current ICount
      // to decide whether or not to emit a short or long branch.
      //
      // short branch:
      // bCC .L_TARGET_MBB
      //
      // long branch:
      // bInverseCC $PC+8
      // b .L_TARGET_MBB
      // b .L_FALLTHROUGH_MBB

      for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
           ++MFI) {
        MachineBasicBlock *MBB = MFI;

        for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end();
             MBBI != EE; ++MBBI) {
          if (MBBI->getOpcode() == PPC::COND_BRANCH) {
            // condbranch operands:
            // 0. CR0 register
            // 1. bc opcode
            // 2. target MBB
            // 3. fallthrough MBB
            MachineBasicBlock *trueMBB =
              MBBI->getOperand(2).getMachineBasicBlock();
            MachineBasicBlock *falseMBB =
              MBBI->getOperand(3).getMachineBasicBlock();

            int Displacement = OffsetMap[trueMBB] - ByteCount;
            unsigned Opcode = MBBI->getOperand(1).getImmedValue();
            unsigned Inverted = PPC32InstrInfo::invertPPCBranchOpcode(Opcode);

            MachineInstr *MI = MBBI;
            if (Displacement >= -32768 && Displacement <= 32767) {
              BuildMI(*MBB, MBBI, Opcode, 2).addReg(PPC::CR0).addMBB(trueMBB);
            } else {
              BuildMI(*MBB, MBBI, Inverted, 2).addReg(PPC::CR0).addSImm(8);
              BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(trueMBB);
              BuildMI(*MBB, MBBI, PPC::B, 1).addMBB(falseMBB);
            }
            MBB->erase(MI);
          }
          ByteCount += bytesForOpcode(MBBI->getOpcode());
        }
      }

      OffsetMap.clear();
      return true;
    }

    virtual const char *getPassName() const {
      return "PowerPC Branch Selection";
    }
  };
}

/// createPPCBranchSelectionPass - returns an instance of the Branch Selection
/// Pass
///
FunctionPass *llvm::createPPCBranchSelectionPass() {
  return new BSel();
}
<|endoftext|>


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

#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <Dedispersion.hpp>
#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <utils.hpp>
#include <Shifts.hpp>
#include <ReadData.hpp>
#include <utils.hpp>

int main(int argc, char * argv[]) {
  unsigned int padding = 0;
  uint8_t inputBits = 0;
  bool printResults = false;
  uint64_t wrongSamples = 0;
  std::string channelsFile;
  AstroData::Observation observation_c;
  AstroData::Observation observation;

  try {
    isa::utils::ArgumentList args(argc, argv);
    printResults = args.getSwitch("-print_results");
    inputBits = args.getSwitchArgument< unsigned int >("-input_bits");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    channelsFile = args.getSwitchArgument< std::string >("-zapped_channels");
    observation.setNrBeams(args.getSwitchArgument< unsigned int >("-beams"));
    observation.setNrSyntheticBeams(args.getSwitchArgument< unsigned int >("-synthetic_beams"));
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-subbands"), args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
    observation.setNrSamplesPerBatch(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMSubbandingRange(args.getSwitchArgument< unsigned int >("-subbanding_dms"), args.getSwitchArgument< float >("-subbanding_dm_first"), args.getSwitchArgument< float >("-subbanding_dm_step"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), 0.0, args.getSwitchArgument< float >("-dm_step"));
    observation_c = observation;
    observation_c.setDMRange(observation.getNrDMsSubbanding() * observation.getNrDMs(), observation.getFirstDMSubbanding(), observation.getDMStep());
  } catch  ( isa::utils::SwitchNotFound & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << "Usage: " << argv[0] << " [-print_results] -input_bits ... -padding ... -zapped_channels ... -beams ... -synthetic_beams ... -min_freq ... -channel_bandwidth ... -samples ... -subbands ... -channels ... -subbanding_dms ... -dms ... -subbanding_dm_first ... -subbanding_dm_step ... -dm_step ..." << std::endl;
    return 1;
  }

  // Allocate memory
  std::vector< inputDataType > dispersedData;
  std::vector< outputDataType > subbandedData;
  std::vector< outputDataType > dedispersedData;
  std::vector< outputDataType > dedispersedData_c;
  std::vector< uint8_t > zappedChannels(observation_c.getNrPaddedChannels(padding / sizeof(uint8_t)));
  std::vector< uint8_t > beamDriver(observation_c.getNrSyntheticBeams() * observation_c.getNrPaddedChannels(padding / sizeof(uint8_t)));
  std::vector< float > * shifts = PulsarSearch::getShifts(observation_c, padding);

  AstroData::readZappedChannels(observation_c, channelsFile, zappedChannels);
  observation_c.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerBatch() + static_cast< unsigned int >(shifts->at(0) * (observation_c.getFirstDM() + ((observation_c.getNrDMs() - 1) * observation_c.getDMStep()))));
  observation.setNrSamplesPerBatchSubbanding(observation.getNrSamplesPerBatch() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));
  observation.setNrSamplesPerSubbandingDispersedChannel(observation.getNrSamplesPerBatchSubbanding() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDMSubbanding() + ((observation.getNrDMsSubbanding() - 1) * observation.getDMSubbandingStep()))));
  if ( inputBits >= 8 ) {
    dispersedData.resize(observation_c.getNrBeams() * observation_c.getNrChannels() * observation.getNrSamplesPerPaddedSubbandingDispersedChannel(padding / sizeof(inputDataType)));
    subbandedData.resize(observation.getNrBeams() * observation.getNrSubbands() * observation.getNrDMsSubbanding()  * observation.getNrSamplesPerPaddedSubbandingDispersedChannel(padding / sizeof(inputDataType)));
    dedispersedData.resize(observation.getNrSyntheticBeams() * (observation.getNrDMsSubbanding() * observation.getNrDMs()) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(inputDataType)));
    dedispersedData_c.resize(observation_c.getNrSyntheticBeams() * observation_c.getNrDMs() * observation_c.getNrSamplesPerPaddedBatch(padding / sizeof(inputDataType)));
  } else {
    dispersedData.resize(observation_c.getNrBeams() * observation_c.getNrChannels() * isa::utils::pad(observation.getNrSamplesPerSubbandingDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType)));
    subbandedData.resize(observation.getNrBeams() * observation.getNrSubbands() * isa::utils::pad(observation.getNrSamplesPerSubbandingDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType)));
    dedispersedData.resize(observation.getNrSyntheticBeams() * (observation.getNrDMsSubbanding() * observation.getNrDMs()) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(inputDataType)));
    dedispersedData_c.resize(observation_c.getNrSyntheticBeams() * observation_c.getNrDMs() * isa::utils::pad(observation_c.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(inputDataType)));
  }

  // Generate data
  srand(time(0));
  for ( unsigned int beam = 0; beam < observation_c.getNrBeams(); beam++ ) {
    for ( unsigned int channel = 0; channel < observation_c.getNrChannels(); channel++ ) {
      for ( unsigned int sample = 0; sample < observation_c.getNrSamplesPerDispersedChannel(); sample++ ) {
        if ( inputBits >= 8 ) {
          dispersedData[(beam * observation_c.getNrChannels() * observation_c.getNrSamplesPerPaddedDispersedChannel(padding / sizeof(inputDataType))) + (channel * observation_c.getNrSamplesPerPaddedDispersedChannel(padding / sizeof(inputDataType))) + sample] = rand() % observation_c.getNrChannels();
        } else {
          unsigned int byte = 0;
          uint8_t firstBit = 0;
          uint8_t value = rand() % inputBits;
          uint8_t buffer = 0;

          byte = sample / (8 / inputBits);
          firstBit = (sample % (8 / inputBits)) * inputBits;
          buffer = dispersedData[(beam * observation_c.getNrChannels() * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + (channel * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + byte];
          for ( unsigned int bit = 0; bit < inputBits; bit++ ) {
            isa::utils::setBit(buffer, isa::utils::getBit(value, bit), firstBit + bit);
          }
          dispersedData[(beam * observation_c.getNrChannels() * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + (channel * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + byte] = buffer;
        }
      }
    }
  }
  // TODO: need a different beamDriver for subbands
  for ( unsigned int beam = 0; beam < observation_c.getNrSyntheticBeams(); beam++ ) {
    for ( unsigned int channel = 0; channel < observation_c.getNrChannels(); channel++ ) {
      beamDriver[(beam * observation_c.getNrPaddedChannels(padding / sizeof(uint8_t))) + channel] = rand() % observation_c.getNrBeams();
    }
  }
  std::fill(subbandedData.begin(), subbandedData.end(), 0);
  std::fill(dedispersedData.begin(), dedispersedData.end(), 0);
  std::fill(dedispersedData_c.begin(), dedispersedData_c.end(), 0);

  // Execute dedispersion
  PulsarSearch::dedispersion< inputDataType, intermediateDataType, outputDataType >(observation_c, zappedChannels, beamDriver, dispersedData, dedispersedData_c, *shifts, padding, inputBits);
  PulsarSearch::subbandDedispersionStepOne< inputDataType, intermediateDataType, outputDataType >(observation, zappedChannels, dispersedData, subbandedData, *shifts, padding, inputBits);
  PulsarSearch::subbandDedispersionStepTwo< outputDataType, intermediateDataType, outputDataType >(observation, beamDriver, subbandedData, dedispersedData, *shifts, padding);

  for ( unsigned int sBeam = 0; sBeam < observation.getNrSyntheticBeams(); sBeam++ ) {
    for ( unsigned int firstStepDM = 0; firstStepDM < observation.getNrDMsSubbanding(); firstStepDM++ ) {
      for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
        if ( printResults ) {
          std::cout << "sBeam: " << sBeam << " DM: " << (firstStepDM * observation.getNrDMs()) + dm << std::endl;
        }
        for ( unsigned int sample = 0; sample < observation.getNrSamplesPerBatch(); sample++ ) {
          if ( !isa::utils::same(dedispersedData[(sBeam * observation.getNrDMsSubbanding() * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (firstStepDM * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (dm * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample], dedispersedData_c[(sBeam * observation_c.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (((firstStepDM * observation.getNrDMs()) + dm) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample]) ) {
            wrongSamples++;
          }
          if ( printResults ) {
            std::cout << dedispersedData[(sBeam * observation.getNrDMsSubbanding() * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (firstStepDM * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (dm * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample] << "," << dedispersedData_c[(sBeam * observation_c.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (((firstStepDM * observation.getNrDMs()) + dm) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample] << " ";
          }
        }
        if ( printResults ) {
          std::cout << std::endl;
        }
      }
    }
  }

  if ( wrongSamples > 0 ) {
    std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / (static_cast< uint64_t >(observation_c.getNrSyntheticBeams()) * observation_c.getNrDMs() * observation_c.getNrSamplesPerBatch()) << "%)." << std::endl;
  } else {
    std::cout << "TEST PASSED." << std::endl;
  }

  return 0;
}

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

#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <Dedispersion.hpp>
#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <utils.hpp>
#include <Shifts.hpp>
#include <ReadData.hpp>
#include <utils.hpp>

int main(int argc, char * argv[]) {
  unsigned int padding = 0;
  uint8_t inputBits = 0;
  bool printResults = false;
  uint64_t wrongSamples = 0;
  std::string channelsFile;
  AstroData::Observation observation_c;
  AstroData::Observation observation;

  try {
    isa::utils::ArgumentList args(argc, argv);
    printResults = args.getSwitch("-print_results");
    inputBits = args.getSwitchArgument< unsigned int >("-input_bits");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    channelsFile = args.getSwitchArgument< std::string >("-zapped_channels");
    observation.setNrBeams(args.getSwitchArgument< unsigned int >("-beams"));
    observation.setNrSyntheticBeams(args.getSwitchArgument< unsigned int >("-synthetic_beams"));
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-subbands"), args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
    observation.setNrSamplesPerBatch(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMSubbandingRange(args.getSwitchArgument< unsigned int >("-subbanding_dms"), args.getSwitchArgument< float >("-subbanding_dm_first"), args.getSwitchArgument< float >("-subbanding_dm_step"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), 0.0, args.getSwitchArgument< float >("-dm_step"));
    observation_c = observation;
    observation_c.setDMRange(observation.getNrDMsSubbanding() * observation.getNrDMs(), observation.getFirstDMSubbanding(), observation.getDMStep());
  } catch  ( isa::utils::SwitchNotFound & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << "Usage: " << argv[0] << " [-print_results] -input_bits ... -padding ... -zapped_channels ... -beams ... -synthetic_beams ... -min_freq ... -channel_bandwidth ... -samples ... -subbands ... -channels ... -subbanding_dms ... -dms ... -subbanding_dm_first ... -subbanding_dm_step ... -dm_step ..." << std::endl;
    return 1;
  }

  // Allocate memory
  std::vector< inputDataType > dispersedData;
  std::vector< outputDataType > subbandedData;
  std::vector< outputDataType > dedispersedData;
  std::vector< outputDataType > dedispersedData_c;
  std::vector< uint8_t > zappedChannels(observation_c.getNrPaddedChannels(padding / sizeof(uint8_t)));
  std::vector< uint8_t > beamDriver(observation_c.getNrSyntheticBeams() * observation_c.getNrPaddedChannels(padding / sizeof(uint8_t)));
  std::vector< uint8_t > beamDriverSubband(observation.getNrSyntheticBeams() * observation.getNrPaddedSubbands(padding / sizeof(uint8_t)));
  std::vector< float > * shifts = PulsarSearch::getShifts(observation_c, padding);

  AstroData::readZappedChannels(observation_c, channelsFile, zappedChannels);
  observation_c.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerBatch() + static_cast< unsigned int >(shifts->at(0) * (observation_c.getFirstDM() + ((observation_c.getNrDMs() - 1) * observation_c.getDMStep()))));
  observation.setNrSamplesPerBatchSubbanding(observation.getNrSamplesPerBatch() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));
  observation.setNrSamplesPerSubbandingDispersedChannel(observation.getNrSamplesPerBatchSubbanding() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDMSubbanding() + ((observation.getNrDMsSubbanding() - 1) * observation.getDMSubbandingStep()))));
  if ( inputBits >= 8 ) {
    dispersedData.resize(observation_c.getNrBeams() * observation_c.getNrChannels() * observation.getNrSamplesPerPaddedSubbandingDispersedChannel(padding / sizeof(inputDataType)));
    subbandedData.resize(observation.getNrBeams() * observation.getNrSubbands() * observation.getNrDMsSubbanding()  * observation.getNrSamplesPerPaddedSubbandingDispersedChannel(padding / sizeof(inputDataType)));
    dedispersedData.resize(observation.getNrSyntheticBeams() * (observation.getNrDMsSubbanding() * observation.getNrDMs()) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(inputDataType)));
    dedispersedData_c.resize(observation_c.getNrSyntheticBeams() * observation_c.getNrDMs() * observation_c.getNrSamplesPerPaddedBatch(padding / sizeof(inputDataType)));
  } else {
    dispersedData.resize(observation_c.getNrBeams() * observation_c.getNrChannels() * isa::utils::pad(observation.getNrSamplesPerSubbandingDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType)));
    subbandedData.resize(observation.getNrBeams() * observation.getNrSubbands() * isa::utils::pad(observation.getNrSamplesPerSubbandingDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType)));
    dedispersedData.resize(observation.getNrSyntheticBeams() * (observation.getNrDMsSubbanding() * observation.getNrDMs()) * isa::utils::pad(observation.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(inputDataType)));
    dedispersedData_c.resize(observation_c.getNrSyntheticBeams() * observation_c.getNrDMs() * isa::utils::pad(observation_c.getNrSamplesPerBatch() / (8 / inputBits), padding / sizeof(inputDataType)));
  }

  // Generate data
  srand(time(0));
  for ( unsigned int beam = 0; beam < observation_c.getNrBeams(); beam++ ) {
    for ( unsigned int channel = 0; channel < observation_c.getNrChannels(); channel++ ) {
      for ( unsigned int sample = 0; sample < observation_c.getNrSamplesPerDispersedChannel(); sample++ ) {
        if ( inputBits >= 8 ) {
          dispersedData[(beam * observation_c.getNrChannels() * observation_c.getNrSamplesPerPaddedDispersedChannel(padding / sizeof(inputDataType))) + (channel * observation_c.getNrSamplesPerPaddedDispersedChannel(padding / sizeof(inputDataType))) + sample] = rand() % observation_c.getNrChannels();
        } else {
          unsigned int byte = 0;
          uint8_t firstBit = 0;
          uint8_t value = rand() % inputBits;
          uint8_t buffer = 0;

          byte = sample / (8 / inputBits);
          firstBit = (sample % (8 / inputBits)) * inputBits;
          buffer = dispersedData[(beam * observation_c.getNrChannels() * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + (channel * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + byte];
          for ( unsigned int bit = 0; bit < inputBits; bit++ ) {
            isa::utils::setBit(buffer, isa::utils::getBit(value, bit), firstBit + bit);
          }
          dispersedData[(beam * observation_c.getNrChannels() * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + (channel * isa::utils::pad(observation_c.getNrSamplesPerDispersedChannel() / (8 / inputBits), padding / sizeof(inputDataType))) + byte] = buffer;
        }
      }
    }
  }
  for ( unsigned int beam = 0; beam < observation_c.getNrSyntheticBeams(); beam++ ) {
    for ( unsigned int subband = 0; subband < observation.getNrSubbands(); subband++ ) {
      beamDriverSubband[(beam * observation.getNrPaddedSubbands(padding / sizeof(uint8_t))) + subband] = rand() % observation.getNrSyntheticBeams();
      for ( unsigned int channel = subband * observation.getNrChannelsPerSubband(); channel < (subband + 1) * observation.getNrChannelsPerSubband(); channel++ ) {
        beamDriver[(beam * observation_c.getNrPaddedChannels(padding / sizeof(uint8_t))) + channel] = beamDriverSubband[(beam * observation.getNrPaddedSubbands(padding / sizeof(uint8_t))) + subband];
      }
    }
  }
  std::fill(subbandedData.begin(), subbandedData.end(), 0);
  std::fill(dedispersedData.begin(), dedispersedData.end(), 0);
  std::fill(dedispersedData_c.begin(), dedispersedData_c.end(), 0);

  // Execute dedispersion
  PulsarSearch::dedispersion< inputDataType, intermediateDataType, outputDataType >(observation_c, zappedChannels, beamDriver, dispersedData, dedispersedData_c, *shifts, padding, inputBits);
  PulsarSearch::subbandDedispersionStepOne< inputDataType, intermediateDataType, outputDataType >(observation, zappedChannels, dispersedData, subbandedData, *shifts, padding, inputBits);
  PulsarSearch::subbandDedispersionStepTwo< outputDataType, intermediateDataType, outputDataType >(observation, beamDriverSubband, subbandedData, dedispersedData, *shifts, padding);

  for ( unsigned int sBeam = 0; sBeam < observation.getNrSyntheticBeams(); sBeam++ ) {
    for ( unsigned int firstStepDM = 0; firstStepDM < observation.getNrDMsSubbanding(); firstStepDM++ ) {
      for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
        if ( printResults ) {
          std::cout << "sBeam: " << sBeam << " DM: " << (firstStepDM * observation.getNrDMs()) + dm << std::endl;
        }
        for ( unsigned int sample = 0; sample < observation.getNrSamplesPerBatch(); sample++ ) {
          if ( !isa::utils::same(dedispersedData[(sBeam * observation.getNrDMsSubbanding() * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (firstStepDM * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (dm * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample], dedispersedData_c[(sBeam * observation_c.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (((firstStepDM * observation.getNrDMs()) + dm) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample]) ) {
            wrongSamples++;
          }
          if ( printResults ) {
            std::cout << dedispersedData[(sBeam * observation.getNrDMsSubbanding() * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (firstStepDM * observation.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (dm * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample] << "," << dedispersedData_c[(sBeam * observation_c.getNrDMs() * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + (((firstStepDM * observation.getNrDMs()) + dm) * observation.getNrSamplesPerPaddedBatch(padding / sizeof(outputDataType))) + sample] << " ";
          }
        }
        if ( printResults ) {
          std::cout << std::endl;
        }
      }
    }
  }

  if ( wrongSamples > 0 ) {
    std::cout << "Wrong samples: " << wrongSamples << " (" << (wrongSamples * 100.0) / (static_cast< uint64_t >(observation_c.getNrSyntheticBeams()) * observation_c.getNrDMs() * observation_c.getNrSamplesPerBatch()) << "%)." << std::endl;
  } else {
    std::cout << "TEST PASSED." << std::endl;
  }

  return 0;
}

<|endoftext|>