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

#include "ASTConsumers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompileOptions.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Timer.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
using namespace clang;
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
    BackendAction Action;
    CompileOptions CompileOpts;
    const std::string &InputFile;
    std::string OutputFile;
    bool GenerateDebugInfo;
    ASTContext *Context;

    Timer LLVMIRGeneration;
    Timer CodeGenerationTime;

    llvm::OwningPtr<CodeGenerator> Gen;

    llvm::Module *TheModule;
    llvm::TargetData *TheTargetData;
    llvm::raw_ostream *AsmOutStream;

    mutable llvm::ModuleProvider *ModuleProvider;
    mutable FunctionPassManager *CodeGenPasses;
    mutable PassManager *PerModulePasses;
    mutable FunctionPassManager *PerFunctionPasses;

    FunctionPassManager *getCodeGenPasses() const;
    PassManager *getPerModulePasses() const;
    FunctionPassManager *getPerFunctionPasses() const;

    void CreatePasses();

    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
    /// IR.
    ///
    /// \return True on success. On failure \arg Error will be set to
    /// a user readable error message.
    bool AddEmitPasses(std::string &Error);

    void EmitAssembly();

  public:
    BackendConsumer(BackendAction action, Diagnostic &Diags,
                    const LangOptions &langopts, const CompileOptions &compopts,
                    const std::string &infile, const std::string &outfile,
                    bool debug) :
      Action(action),
      CompileOpts(compopts),
      InputFile(infile),
      OutputFile(outfile),
      GenerateDebugInfo(debug),
      LLVMIRGeneration("LLVM IR Generation Time"),
      CodeGenerationTime("Code Generation Time"),
      Gen(CreateLLVMCodeGen(Diags, langopts, InputFile, GenerateDebugInfo)),
      TheModule(0), TheTargetData(0), AsmOutStream(0), ModuleProvider(0),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {

      // Enable -time-passes if -ftime-report is enabled.
      llvm::TimePassesIsEnabled = CompileOpts.TimePasses;
    }

    ~BackendConsumer() {
      delete AsmOutStream;
      delete TheTargetData;
      delete ModuleProvider;
      delete CodeGenPasses;
      delete PerModulePasses;
      delete PerFunctionPasses;
    }

    virtual void InitializeTU(TranslationUnit& TU) {
      Context = &TU.getContext();

      if (CompileOpts.TimePasses)
        LLVMIRGeneration.startTimer();

      Gen->InitializeTU(TU);

      TheModule = Gen->GetModule();
      ModuleProvider = new ExistingModuleProvider(TheModule);
      TheTargetData =
        new llvm::TargetData(TU.getContext().Target.getTargetDescription());

      if (CompileOpts.TimePasses)
        LLVMIRGeneration.stopTimer();
    }

    virtual void HandleTopLevelDecl(Decl *D) {
      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                     Context->getSourceManager(),
                                     "LLVM IR generation of declaration");
      if (CompileOpts.TimePasses)
        LLVMIRGeneration.startTimer();

      Gen->HandleTopLevelDecl(D);

      if (CompileOpts.TimePasses)
        LLVMIRGeneration.stopTimer();
    }

    virtual void HandleTranslationUnit(TranslationUnit& TU) {
      {
        PrettyStackTraceString CrashInfo("per-file LLVM IR generation");
        if (CompileOpts.TimePasses)
          LLVMIRGeneration.startTimer();

        Gen->HandleTranslationUnit(TU);

        if (CompileOpts.TimePasses)
          LLVMIRGeneration.stopTimer();
      }

      // EmitAssembly times and registers crash info itself.
      EmitAssembly();

      // Force a flush here in case we never get released.
      if (AsmOutStream)
        AsmOutStream->flush();
    }

    virtual void HandleTagDeclDefinition(TagDecl *D) {
      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                     Context->getSourceManager(),
                                     "LLVM IR generation of declaration");
      Gen->HandleTagDeclDefinition(D);
    }
  };
}

FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
  if (!CodeGenPasses) {
    CodeGenPasses = new FunctionPassManager(ModuleProvider);
    CodeGenPasses->add(new TargetData(*TheTargetData));
  }

  return CodeGenPasses;
}

PassManager *BackendConsumer::getPerModulePasses() const {
  if (!PerModulePasses) {
    PerModulePasses = new PassManager();
    PerModulePasses->add(new TargetData(*TheTargetData));
  }

  return PerModulePasses;
}

FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
  if (!PerFunctionPasses) {
    PerFunctionPasses = new FunctionPassManager(ModuleProvider);
    PerFunctionPasses->add(new TargetData(*TheTargetData));
  }

  return PerFunctionPasses;
}

bool BackendConsumer::AddEmitPasses(std::string &Error) {
  if (Action == Backend_EmitNothing)
    return true;

  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
    AsmOutStream = new raw_stdout_ostream();
    sys::Program::ChangeStdoutToBinary();
  } else {
    if (OutputFile.empty()) {
      llvm::sys::Path Path(InputFile);
      Path.eraseSuffix();
      if (Action == Backend_EmitBC) {
        Path.appendSuffix("bc");
      } else if (Action == Backend_EmitLL) {
        Path.appendSuffix("ll");
      } else {
        Path.appendSuffix("s");
      }
      OutputFile = Path.toString();
    }

    AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), true, Error);
    if (!Error.empty())
      return false;
  }

  if (Action == Backend_EmitBC) {
    getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
  } else if (Action == Backend_EmitLL) {
    getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
  } else {
    bool Fast = CompileOpts.OptimizationLevel == 0;

    // Create the TargetMachine for generating code.
    const TargetMachineRegistry::entry *TME =
      TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
    if (!TME) {
      Error = std::string("Unable to get target machine: ") + Error;
      return false;
    }

    std::string FeaturesStr;
    if (CompileOpts.CPU.size() || CompileOpts.Features.size()) {
      SubtargetFeatures Features;
      Features.setCPU(CompileOpts.CPU);
      for (std::vector<std::string>::iterator
             it = CompileOpts.Features.begin(),
             ie = CompileOpts.Features.end(); it != ie; ++it)
        Features.AddFeature(*it);
      FeaturesStr = Features.getString();
    }
    TargetMachine *TM = TME->CtorFn(*TheModule, FeaturesStr);

    // Set register scheduler & allocation policy.
    RegisterScheduler::setDefault(createDefaultScheduler);
    RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
                                 createLinearScanRegisterAllocator);

    // From llvm-gcc:
    // If there are passes we have to run on the entire module, we do codegen
    // as a separate "pass" after that happens.
    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
    // this for fast -O0 compiles!
    FunctionPassManager *PM = getCodeGenPasses();

    // Normal mode, emit a .s file by running the code generator.
    // Note, this also adds codegenerator level optimization passes.
    switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
                                    TargetMachine::AssemblyFile, Fast)) {
    default:
    case FileModel::Error:
      Error = "Unable to interface with target machine!\n";
      return false;
    case FileModel::AsmFile:
      break;
    }

    if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
      Error = "Unable to interface with target machine!\n";
      return false;
    }
  }

  return true;
}

void BackendConsumer::CreatePasses() {
  // In -O0 if checking is disabled, we don't even have per-function passes.
  if (CompileOpts.VerifyModule)
    getPerFunctionPasses()->add(createVerifierPass());

  if (CompileOpts.OptimizationLevel > 0) {
    FunctionPassManager *PM = getPerFunctionPasses();
    PM->add(createCFGSimplificationPass());
    if (CompileOpts.OptimizationLevel == 1)
      PM->add(createPromoteMemoryToRegisterPass());
    else
      PM->add(createScalarReplAggregatesPass());
    PM->add(createInstructionCombiningPass());
  }

  // For now we always create per module passes.
  PassManager *PM = getPerModulePasses();
  if (CompileOpts.OptimizationLevel > 0) {
    if (CompileOpts.UnitAtATime)
      PM->add(createRaiseAllocationsPass());      // call %malloc -> malloc inst
    PM->add(createCFGSimplificationPass());       // Clean up disgusting code
    PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
    if (CompileOpts.UnitAtATime) {
      PM->add(createGlobalOptimizerPass());       // Optimize out global vars
      PM->add(createGlobalDCEPass());             // Remove unused fns and globs
      PM->add(createIPConstantPropagationPass()); // IP Constant Propagation
      PM->add(createDeadArgEliminationPass());    // Dead argument elimination
    }
    PM->add(createInstructionCombiningPass());    // Clean up after IPCP & DAE
    PM->add(createCFGSimplificationPass());       // Clean up after IPCP & DAE
    if (CompileOpts.UnitAtATime) {
      PM->add(createPruneEHPass());               // Remove dead EH info
      PM->add(createFunctionAttrsPass());         // Set readonly/readnone attrs
    }
    if (CompileOpts.InlineFunctions)
      PM->add(createFunctionInliningPass());      // Inline small functions
    else
      PM->add(createAlwaysInlinerPass());         // Respect always_inline
    if (CompileOpts.OptimizationLevel > 2)
      PM->add(createArgumentPromotionPass());     // Scalarize uninlined fn args
    if (CompileOpts.SimplifyLibCalls)
      PM->add(createSimplifyLibCallsPass());      // Library Call Optimizations
    PM->add(createInstructionCombiningPass());    // Cleanup for scalarrepl.
    PM->add(createJumpThreadingPass());           // Thread jumps.
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createScalarReplAggregatesPass());    // Break up aggregate allocas
    PM->add(createInstructionCombiningPass());    // Combine silly seq's
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createTailCallEliminationPass());     // Eliminate tail calls
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createReassociatePass());             // Reassociate expressions
    PM->add(createLoopRotatePass());              // Rotate Loop
    PM->add(createLICMPass());                    // Hoist loop invariants
    PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false));
//    PM->add(createLoopIndexSplitPass());          // Split loop index
    PM->add(createInstructionCombiningPass());
    PM->add(createIndVarSimplifyPass());          // Canonicalize indvars
    PM->add(createLoopDeletionPass());            // Delete dead loops
    if (CompileOpts.UnrollLoops)
      PM->add(createLoopUnrollPass());            // Unroll small loops
    PM->add(createInstructionCombiningPass());    // Clean up after the unroller
    PM->add(createGVNPass());                     // Remove redundancies
    PM->add(createMemCpyOptPass());               // Remove memcpy / form memset
    PM->add(createSCCPPass());                    // Constant prop with SCCP

    // Run instcombine after redundancy elimination to exploit opportunities
    // opened up by them.
    PM->add(createInstructionCombiningPass());
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createDeadStoreEliminationPass());    // Delete dead stores
    PM->add(createAggressiveDCEPass());           // Delete dead instructions
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs

    if (CompileOpts.UnitAtATime) {
      PM->add(createStripDeadPrototypesPass());   // Get rid of dead prototypes
      PM->add(createDeadTypeEliminationPass());   // Eliminate dead types
    }

    if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
      PM->add(createConstantMergePass());         // Merge dup global constants
  } else {
    PM->add(createAlwaysInlinerPass());
  }
}

/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
  // Silently ignore if we weren't initialized for some reason.
  if (!TheModule || !TheTargetData)
    return;

  TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0);

  // Make sure IR generation is happy with the module. This is
  // released by the module provider.
  Module *M = Gen->ReleaseModule();
  if (!M) {
    // The module has been released by IR gen on failures, do not
    // double free.
    ModuleProvider->releaseModule();
    TheModule = 0;
    return;
  }

  assert(TheModule == M && "Unexpected module change during IR generation");

  CreatePasses();

  std::string Error;
  if (!AddEmitPasses(Error)) {
    // FIXME: Don't fail this way.
    llvm::cerr << "ERROR: " << Error << "\n";
    ::exit(1);
  }

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PrettyStackTraceString CrashInfo("per-function optimization");

    PerFunctionPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses) {
    PrettyStackTraceString CrashInfo("per-module optimization passes");
    PerModulePasses->run(*M);
  }

  if (CodeGenPasses) {
    PrettyStackTraceString CrashInfo("code generation");
    CodeGenPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        CodeGenPasses->run(*I);
    CodeGenPasses->doFinalization();
  }
}

ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                          Diagnostic &Diags,
                                          const LangOptions &LangOpts,
                                          const CompileOptions &CompileOpts,
                                          const std::string& InFile,
                                          const std::string& OutFile,
                                          bool GenerateDebugInfo) {
  // FIXME: If optimizing, disable all debug info generation.  The LLVM
  // optimizer and backend is not ready to handle it when optimizations
  // are enabled.
  if (CompileOpts.OptimizationLevel > 0)
    GenerateDebugInfo = false;

  return new BackendConsumer(Action, Diags, LangOpts, CompileOpts,
                             InFile, OutFile, GenerateDebugInfo);
}
<commit_msg>capitalize for consistency, a crash in regalloc now looks like this:<commit_after>//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "ASTConsumers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompileOptions.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Timer.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/SubtargetFeature.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
using namespace clang;
using namespace llvm;

namespace {
  class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
    BackendAction Action;
    CompileOptions CompileOpts;
    const std::string &InputFile;
    std::string OutputFile;
    bool GenerateDebugInfo;
    ASTContext *Context;

    Timer LLVMIRGeneration;
    Timer CodeGenerationTime;

    llvm::OwningPtr<CodeGenerator> Gen;

    llvm::Module *TheModule;
    llvm::TargetData *TheTargetData;
    llvm::raw_ostream *AsmOutStream;

    mutable llvm::ModuleProvider *ModuleProvider;
    mutable FunctionPassManager *CodeGenPasses;
    mutable PassManager *PerModulePasses;
    mutable FunctionPassManager *PerFunctionPasses;

    FunctionPassManager *getCodeGenPasses() const;
    PassManager *getPerModulePasses() const;
    FunctionPassManager *getPerFunctionPasses() const;

    void CreatePasses();

    /// AddEmitPasses - Add passes necessary to emit assembly or LLVM
    /// IR.
    ///
    /// \return True on success. On failure \arg Error will be set to
    /// a user readable error message.
    bool AddEmitPasses(std::string &Error);

    void EmitAssembly();

  public:
    BackendConsumer(BackendAction action, Diagnostic &Diags,
                    const LangOptions &langopts, const CompileOptions &compopts,
                    const std::string &infile, const std::string &outfile,
                    bool debug) :
      Action(action),
      CompileOpts(compopts),
      InputFile(infile),
      OutputFile(outfile),
      GenerateDebugInfo(debug),
      LLVMIRGeneration("LLVM IR Generation Time"),
      CodeGenerationTime("Code Generation Time"),
      Gen(CreateLLVMCodeGen(Diags, langopts, InputFile, GenerateDebugInfo)),
      TheModule(0), TheTargetData(0), AsmOutStream(0), ModuleProvider(0),
      CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {

      // Enable -time-passes if -ftime-report is enabled.
      llvm::TimePassesIsEnabled = CompileOpts.TimePasses;
    }

    ~BackendConsumer() {
      delete AsmOutStream;
      delete TheTargetData;
      delete ModuleProvider;
      delete CodeGenPasses;
      delete PerModulePasses;
      delete PerFunctionPasses;
    }

    virtual void InitializeTU(TranslationUnit& TU) {
      Context = &TU.getContext();

      if (CompileOpts.TimePasses)
        LLVMIRGeneration.startTimer();

      Gen->InitializeTU(TU);

      TheModule = Gen->GetModule();
      ModuleProvider = new ExistingModuleProvider(TheModule);
      TheTargetData =
        new llvm::TargetData(TU.getContext().Target.getTargetDescription());

      if (CompileOpts.TimePasses)
        LLVMIRGeneration.stopTimer();
    }

    virtual void HandleTopLevelDecl(Decl *D) {
      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                     Context->getSourceManager(),
                                     "LLVM IR generation of declaration");
      if (CompileOpts.TimePasses)
        LLVMIRGeneration.startTimer();

      Gen->HandleTopLevelDecl(D);

      if (CompileOpts.TimePasses)
        LLVMIRGeneration.stopTimer();
    }

    virtual void HandleTranslationUnit(TranslationUnit& TU) {
      {
        PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
        if (CompileOpts.TimePasses)
          LLVMIRGeneration.startTimer();

        Gen->HandleTranslationUnit(TU);

        if (CompileOpts.TimePasses)
          LLVMIRGeneration.stopTimer();
      }

      // EmitAssembly times and registers crash info itself.
      EmitAssembly();

      // Force a flush here in case we never get released.
      if (AsmOutStream)
        AsmOutStream->flush();
    }

    virtual void HandleTagDeclDefinition(TagDecl *D) {
      PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                     Context->getSourceManager(),
                                     "LLVM IR generation of declaration");
      Gen->HandleTagDeclDefinition(D);
    }
  };
}

FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
  if (!CodeGenPasses) {
    CodeGenPasses = new FunctionPassManager(ModuleProvider);
    CodeGenPasses->add(new TargetData(*TheTargetData));
  }

  return CodeGenPasses;
}

PassManager *BackendConsumer::getPerModulePasses() const {
  if (!PerModulePasses) {
    PerModulePasses = new PassManager();
    PerModulePasses->add(new TargetData(*TheTargetData));
  }

  return PerModulePasses;
}

FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
  if (!PerFunctionPasses) {
    PerFunctionPasses = new FunctionPassManager(ModuleProvider);
    PerFunctionPasses->add(new TargetData(*TheTargetData));
  }

  return PerFunctionPasses;
}

bool BackendConsumer::AddEmitPasses(std::string &Error) {
  if (Action == Backend_EmitNothing)
    return true;

  if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
    AsmOutStream = new raw_stdout_ostream();
    sys::Program::ChangeStdoutToBinary();
  } else {
    if (OutputFile.empty()) {
      llvm::sys::Path Path(InputFile);
      Path.eraseSuffix();
      if (Action == Backend_EmitBC) {
        Path.appendSuffix("bc");
      } else if (Action == Backend_EmitLL) {
        Path.appendSuffix("ll");
      } else {
        Path.appendSuffix("s");
      }
      OutputFile = Path.toString();
    }

    AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), true, Error);
    if (!Error.empty())
      return false;
  }

  if (Action == Backend_EmitBC) {
    getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
  } else if (Action == Backend_EmitLL) {
    getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
  } else {
    bool Fast = CompileOpts.OptimizationLevel == 0;

    // Create the TargetMachine for generating code.
    const TargetMachineRegistry::entry *TME =
      TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
    if (!TME) {
      Error = std::string("Unable to get target machine: ") + Error;
      return false;
    }

    std::string FeaturesStr;
    if (CompileOpts.CPU.size() || CompileOpts.Features.size()) {
      SubtargetFeatures Features;
      Features.setCPU(CompileOpts.CPU);
      for (std::vector<std::string>::iterator
             it = CompileOpts.Features.begin(),
             ie = CompileOpts.Features.end(); it != ie; ++it)
        Features.AddFeature(*it);
      FeaturesStr = Features.getString();
    }
    TargetMachine *TM = TME->CtorFn(*TheModule, FeaturesStr);

    // Set register scheduler & allocation policy.
    RegisterScheduler::setDefault(createDefaultScheduler);
    RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
                                 createLinearScanRegisterAllocator);

    // From llvm-gcc:
    // If there are passes we have to run on the entire module, we do codegen
    // as a separate "pass" after that happens.
    // FIXME: This is disabled right now until bugs can be worked out.  Reenable
    // this for fast -O0 compiles!
    FunctionPassManager *PM = getCodeGenPasses();

    // Normal mode, emit a .s file by running the code generator.
    // Note, this also adds codegenerator level optimization passes.
    switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
                                    TargetMachine::AssemblyFile, Fast)) {
    default:
    case FileModel::Error:
      Error = "Unable to interface with target machine!\n";
      return false;
    case FileModel::AsmFile:
      break;
    }

    if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
      Error = "Unable to interface with target machine!\n";
      return false;
    }
  }

  return true;
}

void BackendConsumer::CreatePasses() {
  // In -O0 if checking is disabled, we don't even have per-function passes.
  if (CompileOpts.VerifyModule)
    getPerFunctionPasses()->add(createVerifierPass());

  if (CompileOpts.OptimizationLevel > 0) {
    FunctionPassManager *PM = getPerFunctionPasses();
    PM->add(createCFGSimplificationPass());
    if (CompileOpts.OptimizationLevel == 1)
      PM->add(createPromoteMemoryToRegisterPass());
    else
      PM->add(createScalarReplAggregatesPass());
    PM->add(createInstructionCombiningPass());
  }

  // For now we always create per module passes.
  PassManager *PM = getPerModulePasses();
  if (CompileOpts.OptimizationLevel > 0) {
    if (CompileOpts.UnitAtATime)
      PM->add(createRaiseAllocationsPass());      // call %malloc -> malloc inst
    PM->add(createCFGSimplificationPass());       // Clean up disgusting code
    PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
    if (CompileOpts.UnitAtATime) {
      PM->add(createGlobalOptimizerPass());       // Optimize out global vars
      PM->add(createGlobalDCEPass());             // Remove unused fns and globs
      PM->add(createIPConstantPropagationPass()); // IP Constant Propagation
      PM->add(createDeadArgEliminationPass());    // Dead argument elimination
    }
    PM->add(createInstructionCombiningPass());    // Clean up after IPCP & DAE
    PM->add(createCFGSimplificationPass());       // Clean up after IPCP & DAE
    if (CompileOpts.UnitAtATime) {
      PM->add(createPruneEHPass());               // Remove dead EH info
      PM->add(createFunctionAttrsPass());         // Set readonly/readnone attrs
    }
    if (CompileOpts.InlineFunctions)
      PM->add(createFunctionInliningPass());      // Inline small functions
    else
      PM->add(createAlwaysInlinerPass());         // Respect always_inline
    if (CompileOpts.OptimizationLevel > 2)
      PM->add(createArgumentPromotionPass());     // Scalarize uninlined fn args
    if (CompileOpts.SimplifyLibCalls)
      PM->add(createSimplifyLibCallsPass());      // Library Call Optimizations
    PM->add(createInstructionCombiningPass());    // Cleanup for scalarrepl.
    PM->add(createJumpThreadingPass());           // Thread jumps.
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createScalarReplAggregatesPass());    // Break up aggregate allocas
    PM->add(createInstructionCombiningPass());    // Combine silly seq's
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createTailCallEliminationPass());     // Eliminate tail calls
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs
    PM->add(createReassociatePass());             // Reassociate expressions
    PM->add(createLoopRotatePass());              // Rotate Loop
    PM->add(createLICMPass());                    // Hoist loop invariants
    PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false));
//    PM->add(createLoopIndexSplitPass());          // Split loop index
    PM->add(createInstructionCombiningPass());
    PM->add(createIndVarSimplifyPass());          // Canonicalize indvars
    PM->add(createLoopDeletionPass());            // Delete dead loops
    if (CompileOpts.UnrollLoops)
      PM->add(createLoopUnrollPass());            // Unroll small loops
    PM->add(createInstructionCombiningPass());    // Clean up after the unroller
    PM->add(createGVNPass());                     // Remove redundancies
    PM->add(createMemCpyOptPass());               // Remove memcpy / form memset
    PM->add(createSCCPPass());                    // Constant prop with SCCP

    // Run instcombine after redundancy elimination to exploit opportunities
    // opened up by them.
    PM->add(createInstructionCombiningPass());
    PM->add(createCondPropagationPass());         // Propagate conditionals
    PM->add(createDeadStoreEliminationPass());    // Delete dead stores
    PM->add(createAggressiveDCEPass());           // Delete dead instructions
    PM->add(createCFGSimplificationPass());       // Merge & remove BBs

    if (CompileOpts.UnitAtATime) {
      PM->add(createStripDeadPrototypesPass());   // Get rid of dead prototypes
      PM->add(createDeadTypeEliminationPass());   // Eliminate dead types
    }

    if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
      PM->add(createConstantMergePass());         // Merge dup global constants
  } else {
    PM->add(createAlwaysInlinerPass());
  }
}

/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
  // Silently ignore if we weren't initialized for some reason.
  if (!TheModule || !TheTargetData)
    return;

  TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0);

  // Make sure IR generation is happy with the module. This is
  // released by the module provider.
  Module *M = Gen->ReleaseModule();
  if (!M) {
    // The module has been released by IR gen on failures, do not
    // double free.
    ModuleProvider->releaseModule();
    TheModule = 0;
    return;
  }

  assert(TheModule == M && "Unexpected module change during IR generation");

  CreatePasses();

  std::string Error;
  if (!AddEmitPasses(Error)) {
    // FIXME: Don't fail this way.
    llvm::cerr << "ERROR: " << Error << "\n";
    ::exit(1);
  }

  // Run passes. For now we do all passes at once, but eventually we
  // would like to have the option of streaming code generation.

  if (PerFunctionPasses) {
    PrettyStackTraceString CrashInfo("Per-function optimization");

    PerFunctionPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        PerFunctionPasses->run(*I);
    PerFunctionPasses->doFinalization();
  }

  if (PerModulePasses) {
    PrettyStackTraceString CrashInfo("Per-module optimization passes");
    PerModulePasses->run(*M);
  }

  if (CodeGenPasses) {
    PrettyStackTraceString CrashInfo("Code generation");
    CodeGenPasses->doInitialization();
    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
      if (!I->isDeclaration())
        CodeGenPasses->run(*I);
    CodeGenPasses->doFinalization();
  }
}

ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
                                          Diagnostic &Diags,
                                          const LangOptions &LangOpts,
                                          const CompileOptions &CompileOpts,
                                          const std::string& InFile,
                                          const std::string& OutFile,
                                          bool GenerateDebugInfo) {
  // FIXME: If optimizing, disable all debug info generation.  The LLVM
  // optimizer and backend is not ready to handle it when optimizations
  // are enabled.
  if (CompileOpts.OptimizationLevel > 0)
    GenerateDebugInfo = false;

  return new BackendConsumer(Action, Diags, LangOpts, CompileOpts,
                             InFile, OutFile, GenerateDebugInfo);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_apitest.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Tabs) {
  ASSERT_TRUE(StartHTTPServer());

  // The test creates a tab and checks that the URL of the new tab
  // is that of the new tab page.  Make sure the pref that controls
  // this is set.
  browser()->profile()->GetPrefs()->SetBoolean(
      prefs::kHomePageIsNewTabPage, true);

  ASSERT_TRUE(RunExtensionTest("tabs/basics")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabGetCurrent) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/get_current")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabConnect) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/connect")) << message_;
}

#if defined(TOOLKIT_VIEWS) && defined(OS_LINUX)
// The way ChromeOs deals with browser windows breaks this test.
// http://crbug.com/43440.
#define MAYBE_TabOnRemoved DISABLED_TabOnRemoved
#else
#define MAYBE_TabOnRemoved TabOnRemoved
#endif
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabOnRemoved) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/on_removed")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CaptureVisibleTab) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/capture_visible_tab")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabsOnUpdated) {
  ASSERT_TRUE(StartHTTPServer());

  ASSERT_TRUE(RunExtensionTest("tabs/on_updated")) << message_;
}
<commit_msg>Remove #define cruft around ExtensionApiTest.TabOnRemoved.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_apitest.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/common/pref_names.h"

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Tabs) {
  ASSERT_TRUE(StartHTTPServer());

  // The test creates a tab and checks that the URL of the new tab
  // is that of the new tab page.  Make sure the pref that controls
  // this is set.
  browser()->profile()->GetPrefs()->SetBoolean(
      prefs::kHomePageIsNewTabPage, true);

  ASSERT_TRUE(RunExtensionTest("tabs/basics")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabGetCurrent) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/get_current")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabConnect) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/connect")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabOnRemoved) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/on_removed")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CaptureVisibleTab) {
  ASSERT_TRUE(StartHTTPServer());
  ASSERT_TRUE(RunExtensionTest("tabs/capture_visible_tab")) << message_;
}

IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TabsOnUpdated) {
  ASSERT_TRUE(StartHTTPServer());

  ASSERT_TRUE(RunExtensionTest("tabs/on_updated")) << message_;
}
<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif // HAVE_CMAKE_CONFIG

#if HAVE_EIGEN

#include <dune/stuff/common/float_cmp.hh>

#include "affine.hh"
#include "eigen.hh"

namespace Dune {
namespace Pymor {
namespace LA {

// ============================
// ===== EigenDenseVector =====
// ============================
template< class S >
EigenDenseVector< S >::EigenDenseVector(const int size, const ScalarType value)
  : backend_(new BackendType(assert_is_not_negative(size), value))
{}

template< class S >
EigenDenseVector< S >::EigenDenseVector(BackendType* backend_ptr)
  : backend_(backend_ptr)
{}

template< class S >
EigenDenseVector< S >::EigenDenseVector(std::shared_ptr< BackendType > backend_ptr)
  : backend_(std::move(backend_ptr))
{}

template< class S >
EigenDenseVector< S >::EigenDenseVector(const ThisType& other)
  : backend_(other.backend_)
{}

template< class S >
typename EigenDenseVector< S >::ThisType& EigenDenseVector< S >::operator=(const ThisType& other)
{
  backend_ = other.backend_;
  return *this;
}

template< class S >
typename EigenDenseVector< S >::ThisType EigenDenseVector< S >::copy() const
{
  return EigenDenseVector< S >(new BackendType(*backend_));
}

template< class S >
void EigenDenseVector< S >::scal(const ScalarType& alpha)
{
  ensure_uniqueness();
  backend_->backend() *= alpha;
}

template< class S >
void EigenDenseVector< S >::axpy(const ScalarType& alpha, const ThisType& xx) throw (Exception::sizes_do_not_match)
{
  ensure_uniqueness();
  auto& thisRef = *backend_;
  const auto& xRef = *(xx.backend_);
  thisRef.backend() += alpha * xRef.backend();
}

template< class S >
unsigned int EigenDenseVector< S >::dim() const
{
  return backend_->size();
}

template< class S >
bool EigenDenseVector< S >::has_equal_shape(const ThisType& other) const
{
  return dim() == other.dim();
}

template< class S >
bool EigenDenseVector< S >::almost_equal(const ThisType& other,
                                         const ScalarType epsilon) const
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  return Dune::Stuff::Common::FloatCmp::eq(*backend_, *(other.backend_), epsilon);
} // ... almost_equal(...)

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::dot(const ThisType& other) const
  throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  return backend_->backend().transpose() * other.backend_->backend();
}

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::l1_norm() const
{
  return backend_->backend().template lpNorm< 1 >();
}

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::l2_norm() const
{
  return backend_->backend().norm();
}

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::sup_norm() const
{
  return backend_->backend().template lpNorm< ::Eigen::Infinity >();
}

template< class S >
std::vector< typename EigenDenseVector< S >::ScalarType >
EigenDenseVector< S >::components(const std::vector< int >& component_indices) const
  throw (Exception::sizes_do_not_match, Exception::index_out_of_range)
{
  if (component_indices.size() > dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "size of component_indices (" << component_indices.size()
                     << ") is larger than the dim of this (" << dim() << ")!");
  std::vector< double > values(component_indices.size(), 0);
  for (size_t ii = 0; ii < component_indices.size(); ++ii) {
    const int component = component_indices[ii];
    if (component < 0)
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "component_indices[" << ii << "] is negative (" << component << ")!");
    if (component >= int(dim()))
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "component_indices[" << ii << "] is too large for this (" << dim() << ")!");
    values[ii] = backend_->backend()[component];
  }
  return values;
} // ... components(...)

template< class S >
std::vector< typename EigenDenseVector< S >::ScalarType > EigenDenseVector< S >::amax() const
{
  std::vector< ScalarType > result(2, ScalarType(0));
  size_t minIndex = 0;
  size_t maxIndex = 0;
  const ScalarType minimum = backend_->backend().minCoeff(&minIndex);
  const ScalarType maximum = backend_->backend().maxCoeff(&maxIndex);
  if (std::abs(maximum) >= std::abs(minimum)) {
    result[0] = minIndex;
    result[1] = std::abs(minimum);
  } else {
    result[0] = maxIndex;
    result[1] = maximum;
  }
  return result;
} // ... amax(...)

template< class S >
void EigenDenseVector< S >::add(const ThisType& other, ThisType& result) const
  throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  result.backend_->backend() = backend_->backend() + other.backend_->backend();
}

template< class S >
void EigenDenseVector< S >::iadd(const ThisType& other) throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  ensure_uniqueness();
  backend_->backend() += other.backend_->backend();
}

template< class S >
void EigenDenseVector< S >::sub(const ThisType& other, ThisType& result) const
  throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  for (unsigned int ii = 0; ii < dim(); ++ii)
    result.backend_->backend() = backend_->backend() - other.backend_->backend();
}

template< class S >
void EigenDenseVector< S >::isub(const ThisType& other) throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  ensure_uniqueness();
  backend_->backend() -= other.backend_->backend();
}

template< class S >
typename EigenDenseVector< S >::BackendType& EigenDenseVector< S >::backend()
{
  ensure_uniqueness();
  return *backend_;
}

template< class S >
const typename EigenDenseVector< S >::BackendType& EigenDenseVector< S >::backend() const
{
  const_cast< ThisType& >(*this).ensure_uniqueness();
  return *backend_;
}

template< class S >
int EigenDenseVector< S >::assert_is_not_negative(const int ii) throw (Exception::index_out_of_range)
{
  if (ii < 0) DUNE_PYMOR_THROW(Exception::index_out_of_range, "ii has to be positive (is " << ii << ")!");
  return ii;
}

template< class S >
inline void EigenDenseVector< S >::ensure_uniqueness()
{
  if (!backend_.unique())
    backend_ = std::make_shared< BackendType >(*backend_);
}

template class EigenDenseVector< double >;
template class AffinelyDecomposedConstContainer< EigenDenseVector< double > >;
template class AffinelyDecomposedContainer< EigenDenseVector< double > >;

// =====================================
// ===== EigenRowMajorSparseMatrix =====
// =====================================
template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix()
  : backend_(new BackendType())
{}

template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix(BackendType* backend_ptr)
  : backend_(backend_ptr)
{}

template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix(std::shared_ptr< BackendType >& backend_ptr)
  : backend_(backend_ptr)
{}

template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix(const ThisType& other)
  : backend_(other.backend_)
{}

template< class S >
typename EigenRowMajorSparseMatrix< S >::ThisType& EigenRowMajorSparseMatrix< S >::operator=(const ThisType& other)
{
  backend_ = other.backend_;
  return *this;
}

template< class S >
typename EigenRowMajorSparseMatrix< S >::ThisType EigenRowMajorSparseMatrix< S >::copy() const
{
  return EigenRowMajorSparseMatrix< S >(new BackendType(*backend_));
}

template< class S >
unsigned int EigenRowMajorSparseMatrix< S >::dim_source() const
{
  return backend_->cols();
}

template< class S >
unsigned int EigenRowMajorSparseMatrix< S >::dim_range() const
{
  return backend_->rows();
}

template< class S >
bool EigenRowMajorSparseMatrix< S >::has_equal_shape(const ThisType& other) const
{
  return dim_source() == other.dim_source() && dim_range() == other.dim_range();
}

template< class S >
void EigenRowMajorSparseMatrix< S >::scal(const ScalarType& alpha)
{
  ensure_uniqueness();
  backend_->backend() *= alpha;
}

template< class S >
void EigenRowMajorSparseMatrix< S >::axpy(const ScalarType& alpha, const ThisType& xx) throw (Exception::sizes_do_not_match)
{
  if (xx.dim_source() != dim_source())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "the dim_source of xx (" << xx.dim_source() << ") does not match the dim_source of this ("
                     << dim_source() << ")!");
  if (xx.dim_range() != dim_range())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "the dim_range of xx (" << xx.dim_range() << ") does not match the dim_range of this ("
                     << dim_range() << ")!");
  ensure_uniqueness();
  backend_->backend() += alpha * xx.backend_->backend();
}

template< class S >
typename EigenRowMajorSparseMatrix< S >::BackendType& EigenRowMajorSparseMatrix< S >::backend()
{
  ensure_uniqueness();
  return *backend_;
}

template< class S >
const typename EigenRowMajorSparseMatrix< S >::BackendType& EigenRowMajorSparseMatrix< S >::backend() const
{
  const_cast< ThisType& >(*this).ensure_uniqueness();
  return *backend_;
}

template< class S >
inline void EigenRowMajorSparseMatrix< S >::ensure_uniqueness()
{
  if (!backend_.unique())
    backend_ = std::make_shared< BackendType >(*backend_);
}

template class EigenRowMajorSparseMatrix< double >;
template class AffinelyDecomposedConstContainer< EigenRowMajorSparseMatrix< double > >;
template class AffinelyDecomposedContainer< EigenRowMajorSparseMatrix< double > >;

} // namespace LA
} // namespace Pymor
} // namespace Dune

#endif // HAVE_EIGEN
<commit_msg>[la.container.eigen] fixed wrong type<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif // HAVE_CMAKE_CONFIG

#if HAVE_EIGEN

#include <dune/stuff/common/float_cmp.hh>

#include "affine.hh"
#include "eigen.hh"

namespace Dune {
namespace Pymor {
namespace LA {

// ============================
// ===== EigenDenseVector =====
// ============================
template< class S >
EigenDenseVector< S >::EigenDenseVector(const int size, const ScalarType value)
  : backend_(new BackendType(assert_is_not_negative(size), value))
{}

template< class S >
EigenDenseVector< S >::EigenDenseVector(BackendType* backend_ptr)
  : backend_(backend_ptr)
{}

template< class S >
EigenDenseVector< S >::EigenDenseVector(std::shared_ptr< BackendType > backend_ptr)
  : backend_(std::move(backend_ptr))
{}

template< class S >
EigenDenseVector< S >::EigenDenseVector(const ThisType& other)
  : backend_(other.backend_)
{}

template< class S >
typename EigenDenseVector< S >::ThisType& EigenDenseVector< S >::operator=(const ThisType& other)
{
  backend_ = other.backend_;
  return *this;
}

template< class S >
typename EigenDenseVector< S >::ThisType EigenDenseVector< S >::copy() const
{
  return EigenDenseVector< S >(new BackendType(*backend_));
}

template< class S >
void EigenDenseVector< S >::scal(const ScalarType& alpha)
{
  ensure_uniqueness();
  backend_->backend() *= alpha;
}

template< class S >
void EigenDenseVector< S >::axpy(const ScalarType& alpha, const ThisType& xx) throw (Exception::sizes_do_not_match)
{
  ensure_uniqueness();
  auto& thisRef = *backend_;
  const auto& xRef = *(xx.backend_);
  thisRef.backend() += alpha * xRef.backend();
}

template< class S >
unsigned int EigenDenseVector< S >::dim() const
{
  return backend_->size();
}

template< class S >
bool EigenDenseVector< S >::has_equal_shape(const ThisType& other) const
{
  return dim() == other.dim();
}

template< class S >
bool EigenDenseVector< S >::almost_equal(const ThisType& other,
                                         const ScalarType epsilon) const
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  return Dune::Stuff::Common::FloatCmp::eq(*backend_, *(other.backend_), epsilon);
} // ... almost_equal(...)

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::dot(const ThisType& other) const
  throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  return backend_->backend().transpose() * other.backend_->backend();
}

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::l1_norm() const
{
  return backend_->backend().template lpNorm< 1 >();
}

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::l2_norm() const
{
  return backend_->backend().norm();
}

template< class S >
typename EigenDenseVector< S >::ScalarType EigenDenseVector< S >::sup_norm() const
{
  return backend_->backend().template lpNorm< ::Eigen::Infinity >();
}

template< class S >
std::vector< typename EigenDenseVector< S >::ScalarType >
EigenDenseVector< S >::components(const std::vector< int >& component_indices) const
  throw (Exception::sizes_do_not_match, Exception::index_out_of_range)
{
  if (component_indices.size() > dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "size of component_indices (" << component_indices.size()
                     << ") is larger than the dim of this (" << dim() << ")!");
  std::vector< ScalarType > values(component_indices.size(), 0);
  for (size_t ii = 0; ii < component_indices.size(); ++ii) {
    const int component = component_indices[ii];
    if (component < 0)
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "component_indices[" << ii << "] is negative (" << component << ")!");
    if (component >= int(dim()))
      DUNE_PYMOR_THROW(Exception::index_out_of_range,
                       "component_indices[" << ii << "] is too large for this (" << dim() << ")!");
    values[ii] = backend_->backend()[component];
  }
  return values;
} // ... components(...)

template< class S >
std::vector< typename EigenDenseVector< S >::ScalarType > EigenDenseVector< S >::amax() const
{
  std::vector< ScalarType > result(2, ScalarType(0));
  size_t minIndex = 0;
  size_t maxIndex = 0;
  const ScalarType minimum = backend_->backend().minCoeff(&minIndex);
  const ScalarType maximum = backend_->backend().maxCoeff(&maxIndex);
  if (std::abs(maximum) >= std::abs(minimum)) {
    result[0] = minIndex;
    result[1] = std::abs(minimum);
  } else {
    result[0] = maxIndex;
    result[1] = maximum;
  }
  return result;
} // ... amax(...)

template< class S >
void EigenDenseVector< S >::add(const ThisType& other, ThisType& result) const
  throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  result.backend_->backend() = backend_->backend() + other.backend_->backend();
}

template< class S >
void EigenDenseVector< S >::iadd(const ThisType& other) throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  ensure_uniqueness();
  backend_->backend() += other.backend_->backend();
}

template< class S >
void EigenDenseVector< S >::sub(const ThisType& other, ThisType& result) const
  throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  for (unsigned int ii = 0; ii < dim(); ++ii)
    result.backend_->backend() = backend_->backend() - other.backend_->backend();
}

template< class S >
void EigenDenseVector< S >::isub(const ThisType& other) throw (Exception::sizes_do_not_match)
{
  if (dim() != other.dim())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "dim of other (" << other.dim() << ") does not match the dim of this (" << dim() << ")!");
  ensure_uniqueness();
  backend_->backend() -= other.backend_->backend();
}

template< class S >
typename EigenDenseVector< S >::BackendType& EigenDenseVector< S >::backend()
{
  ensure_uniqueness();
  return *backend_;
}

template< class S >
const typename EigenDenseVector< S >::BackendType& EigenDenseVector< S >::backend() const
{
  const_cast< ThisType& >(*this).ensure_uniqueness();
  return *backend_;
}

template< class S >
int EigenDenseVector< S >::assert_is_not_negative(const int ii) throw (Exception::index_out_of_range)
{
  if (ii < 0) DUNE_PYMOR_THROW(Exception::index_out_of_range, "ii has to be positive (is " << ii << ")!");
  return ii;
}

template< class S >
inline void EigenDenseVector< S >::ensure_uniqueness()
{
  if (!backend_.unique())
    backend_ = std::make_shared< BackendType >(*backend_);
}

template class EigenDenseVector< double >;
template class AffinelyDecomposedConstContainer< EigenDenseVector< double > >;
template class AffinelyDecomposedContainer< EigenDenseVector< double > >;

// =====================================
// ===== EigenRowMajorSparseMatrix =====
// =====================================
template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix()
  : backend_(new BackendType())
{}

template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix(BackendType* backend_ptr)
  : backend_(backend_ptr)
{}

template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix(std::shared_ptr< BackendType >& backend_ptr)
  : backend_(backend_ptr)
{}

template< class S >
EigenRowMajorSparseMatrix< S >::EigenRowMajorSparseMatrix(const ThisType& other)
  : backend_(other.backend_)
{}

template< class S >
typename EigenRowMajorSparseMatrix< S >::ThisType& EigenRowMajorSparseMatrix< S >::operator=(const ThisType& other)
{
  backend_ = other.backend_;
  return *this;
}

template< class S >
typename EigenRowMajorSparseMatrix< S >::ThisType EigenRowMajorSparseMatrix< S >::copy() const
{
  return EigenRowMajorSparseMatrix< S >(new BackendType(*backend_));
}

template< class S >
unsigned int EigenRowMajorSparseMatrix< S >::dim_source() const
{
  return backend_->cols();
}

template< class S >
unsigned int EigenRowMajorSparseMatrix< S >::dim_range() const
{
  return backend_->rows();
}

template< class S >
bool EigenRowMajorSparseMatrix< S >::has_equal_shape(const ThisType& other) const
{
  return dim_source() == other.dim_source() && dim_range() == other.dim_range();
}

template< class S >
void EigenRowMajorSparseMatrix< S >::scal(const ScalarType& alpha)
{
  ensure_uniqueness();
  backend_->backend() *= alpha;
}

template< class S >
void EigenRowMajorSparseMatrix< S >::axpy(const ScalarType& alpha, const ThisType& xx) throw (Exception::sizes_do_not_match)
{
  if (xx.dim_source() != dim_source())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "the dim_source of xx (" << xx.dim_source() << ") does not match the dim_source of this ("
                     << dim_source() << ")!");
  if (xx.dim_range() != dim_range())
    DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                     "the dim_range of xx (" << xx.dim_range() << ") does not match the dim_range of this ("
                     << dim_range() << ")!");
  ensure_uniqueness();
  backend_->backend() += alpha * xx.backend_->backend();
}

template< class S >
typename EigenRowMajorSparseMatrix< S >::BackendType& EigenRowMajorSparseMatrix< S >::backend()
{
  ensure_uniqueness();
  return *backend_;
}

template< class S >
const typename EigenRowMajorSparseMatrix< S >::BackendType& EigenRowMajorSparseMatrix< S >::backend() const
{
  const_cast< ThisType& >(*this).ensure_uniqueness();
  return *backend_;
}

template< class S >
inline void EigenRowMajorSparseMatrix< S >::ensure_uniqueness()
{
  if (!backend_.unique())
    backend_ = std::make_shared< BackendType >(*backend_);
}

template class EigenRowMajorSparseMatrix< double >;
template class AffinelyDecomposedConstContainer< EigenRowMajorSparseMatrix< double > >;
template class AffinelyDecomposedContainer< EigenRowMajorSparseMatrix< double > >;

} // namespace LA
} // namespace Pymor
} // namespace Dune

#endif // HAVE_EIGEN
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_GRIDS_PROVIDER_CUBE_HH
#define DUNE_STUFF_GRIDS_PROVIDER_CUBE_HH

#include <memory>
#include <sstream>
#include <type_traits>
#include <vector>
#include <array>

#include <boost/assign/list_of.hpp>

#include <dune/common/static_assert.hh>

#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/grid/sgrid.hh>
#include <dune/grid/yaspgrid.hh>
#if HAVE_ALUGRID
# include <dune/grid/alugrid.hh>
#endif

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/configtree.hh>
#include <dune/stuff/common/memory.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {
namespace Grids {
namespace internal {

template< typename GridType >
struct ElementVariant;

template< typename GridType >
struct ElementVariant
{
  static const int id = 2;
};

template< int dim >
struct ElementVariant< Dune::YaspGrid< dim > >
{
  static const int id = 1;
};

template< int dim >
struct ElementVariant< Dune::SGrid< dim, dim > >
{
  static const int id = 1;
};

#if HAVE_ALUGRID

template< int dim >
struct ElementVariant< Dune::ALUCubeGrid< dim, dim > >
{
  static const int id = 1;
};

#endif // HAVE_ALUGRID

} // namespace internal

#if HAVE_DUNE_GRID

/**
 *  \brief  Creates a grid of a cube in various dimensions.
 *
 *          Default implementation using the Dune::StructuredGridFactory to create a grid of a cube in 1, 2 or 3
 *          dimensions. Tested with
 *

 \c YASPGRID, \c variant 1, dim = 1, 2, 3,
 *
 \c SGRID, \c variant 1, dim = 1, 2, 3,
 *
 \c ALUGRID_SIMPLEX, \c variant 2, dim = 2, 3,
 *
 \c ALUGRID_CONFORM, \c variant 2, dim = 2, 2 and
 *
 \c ALUGRID_CUBE, \c variant 1, dim = 2, 3.

 *  \tparam GridImp
 *          Type of the underlying grid.
 *  \tparam variant
 *          Type of the codim 0 elements:
 *

\c 1: cubes
 *
2: simplices

 **/
template< typename GridImp, int variant = internal::ElementVariant< GridImp >::id >
class CubeProvider
  : public ProviderInterface< GridImp >
{
  typedef ProviderInterface< GridImp > BaseType;
  typedef CubeProvider< GridImp, variant > ThisType;
public:
  using typename BaseType::GridType;
  static const unsigned int dimDomain = BaseType::dimDomain;
  using typename BaseType::DomainFieldType;
  using typename BaseType::DomainType;

  static const std::string static_id()
  {
    return BaseType::static_id() + ".cube";
  }

  virtual std::string id() /*DS_OVERRIDE*/
  {
    return BaseType::static_id() + ".cube";
  }

  /**
   *  \brief      Creates a cube.
   *  \param[in]  _lowerLeft
   *              A double that is used as a lower left corner in each dimension.
   *  \param[in]  _upperRight
   *              A double that is used as a upper right corner in each dimension.
   *  \param[in]  numElements (optional)
   *              number of elements.
   **/
  CubeProvider(const double _lowerLeft = 0.0, const double _upperRight = 1.0, const unsigned int numElements = 1u)
    : lower_left_(_lowerLeft)
    , upper_right_(_upperRight)
  {
    std::array< unsigned int, dimDomain > tmpNumElements;
    std::fill(tmpNumElements.begin(), tmpNumElements.end(), numElements);
    buildGrid(tmpNumElements);
  }

  CubeProvider(const std::vector< double >& lL, const std::vector< double >& uR, const std::vector< unsigned int >& nE)
  {
    if (lL.size() < dimDomain)
      DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                            "lL has to be at least of size " << dimDomain << " (is " << lL.size() << ")!");
    if (uR.size() < dimDomain)
      DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                            "uR has to be at least of size " << dimDomain << " (is " << uR.size() << ")!");
    if (nE.size() < dimDomain)
      DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                            "nE has to be at least of size " << dimDomain << " (is " << nE.size() << ")!");
    std::array< unsigned int, dimDomain > num_elements;
    for (unsigned int ii = 0; ii < dimDomain; ++ii) {
      lower_left_[ii] = lL[ii];
      upper_right_[ii] = uR[ii];
      num_elements[ii] = nE[ii];
    }
    buildGrid(num_elements);
  }

  /**
   *  \brief      Creates a cube.
   *  \param[in]  _lowerLeft
   *              A vector that is used as a lower left corner.
   *  \param[in]  _upperRight
   *              A vector that is used as a upper right corner.
   *  \param[in]  numElements (optional)
   *              number of elements.
   **/
  CubeProvider(const DomainType& _lowerLeft, const DomainType& _upperRight, const unsigned int numElements = 1u)
    : lower_left_(_lowerLeft)
    , upper_right_(_upperRight)
  {
    std::array< unsigned int, dimDomain > tmpNumElements;
    std::fill(tmpNumElements.begin(), tmpNumElements.end(), numElements);
    buildGrid(tmpNumElements);
  }

  /**
    \brief      Creates a cube. This signature allows to prescribe anisotopic refinement
    \param[in]  _lowerLeft
                A double that is used as a lower left corner in each dimension.
    \param[in]  _upperRight
                A double that is used as a upper right corner in each dimension.
    \param[in]  numElements
                number of elements in each dimension.
                can contain 0 to dim elements (missing dimension are initialized to 1)
    \tparam ContainerType some sequence type that functions with std::begin/end
    **/
  template< class ContainerType  >
  CubeProvider(const DomainType& _lowerLeft, const DomainType& _upperRight,
               const ContainerType numElements
                  = boost::assign::list_of< typename ContainerType::value_type>().repeat(dimDomain,
                                                                                typename ContainerType::value_type(1u)))
    : lower_left_(_lowerLeft),
      upper_right_(_upperRight)
  {
    std::array< unsigned int, dimDomain > tmpNumElements;
    static_assert(std::is_unsigned< typename ContainerType::value_type >::value
                  && std::is_integral< typename ContainerType::value_type >::value,
                  "only unsigned integral number of elements per dimension allowed");
    //base init in case input is shorter
    std::fill(tmpNumElements.begin(), tmpNumElements.end(), 1u);
    std::copy(numElements.begin(), numElements.end(), tmpNumElements.begin());
    buildGrid(tmpNumElements);
  }

  static ParameterTree default_config(const std::string sub_name = "")
  {
    Common::ConfigTree config;
    config["lower_left"] = "[0.0; 0.0; 0.0]";
    config["upper_right"] = "[1.0; 1.0; 1.0]";
    config["num_elements"] = "[8; 8; 8]";
    if (sub_name.empty())
      return config;
    else {
      Common::ConfigTree tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Common::ConfigTree config = default_config(),
                                            const std::string sub_name = static_id())
  {
    // get correct config
    Common::ConfigTree cfg;
    if (config.has_sub(sub_name))
      cfg = config.sub(sub_name);
    else
      cfg = config;
    // extract needed data
    try {
      // try to get vectors
      auto lower_left = cfg.get< DomainType >("lower_left", dimDomain);
      auto upper_right = cfg.get< DomainType >("upper_right", dimDomain);
      auto num_elements = cfg.get< std::vector< unsigned int > >("num_elements", dimDomain);
      return Common::make_unique< ThisType >(lower_left, upper_right, num_elements);
    } catch (Exceptions::configuration_error&) {
      // get scalars
      auto lower_left = cfg.get< DomainFieldType >("lower_left");
      auto upper_right = cfg.get< DomainFieldType >("upper_right");
      auto num_elements = cfg.get< unsigned int >("num_elements");
      return Common::make_unique< ThisType >(lower_left, upper_right, num_elements);
    }
  } // ... create(...)

  virtual std::shared_ptr< GridType >& grid() /*DS_OVERRIDE*/
  {
    return grid_;
  }

  virtual const std::shared_ptr< const GridType >& grid() const /*DS_OVERRIDE*/
  {
    return grid_;
  }

  const DomainType& lower_left() const
  {
    return lower_left_;
  }

  const DomainType& upper_right() const
  {
    return upper_right_;
  }

private:
  void buildGrid(const std::array< unsigned int, dimDomain >& numElements)
  {
    static_assert(variant == 1 || variant == 2, "variant has to be 1 or 2!");
    for (unsigned int dd = 0; dd < dimDomain; ++dd) {
      if (!(lower_left_[dd] < upper_right_[dd]))
        DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                              "lower_left has to be elementwise smaller than upper_right!\n\n"
                              << lower_left_[dd] << " vs. " << upper_right_[dd]);
    }
    switch (variant) {
      case 1:
        grid_ = Dune::StructuredGridFactory< GridType >::createCubeGrid(lower_left_, upper_right_, numElements);
        break;
      case 2:
    default:
        grid_ = Dune::StructuredGridFactory< GridType >::createSimplexGrid(lower_left_, upper_right_, numElements);
        break;
    }
  } // void buildGrid(const DomainType& lowerLeft, const DomainType& upperRight)

  DomainType lower_left_;
  DomainType upper_right_;
  std::shared_ptr< GridType > grid_;
}; // class CubeProvider

#else // HAVE_DUNE_GRID

template< typename GridImp, int variant = 1 >
class CubeProvider
{
  static_assert(AlwaysFalse< GridImp >::value, "You are missing dune-grid!");
};

#endif // HAVE_DUNE_GRID

} // namespace Grids
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_GRIDS_PROVIDER_CUBE_HH
<commit_msg>[grid.provider.cube] renamed to Grid::Providers::Cube<commit_after>// This file is part of the dune-stuff project:
//   https://users.dune-project.org/projects/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_GRIDS_PROVIDER_CUBE_HH
#define DUNE_STUFF_GRIDS_PROVIDER_CUBE_HH

#include <memory>
#include <sstream>
#include <type_traits>
#include <vector>
#include <array>

#include <boost/assign/list_of.hpp>

#include <dune/common/static_assert.hh>

#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/grid/sgrid.hh>
#include <dune/grid/yaspgrid.hh>
#if HAVE_ALUGRID
# include <dune/grid/alugrid.hh>
#endif

#include <dune/stuff/common/exceptions.hh>
#include <dune/stuff/common/configtree.hh>
#include <dune/stuff/common/memory.hh>

#include "interface.hh"

namespace Dune {
namespace Stuff {
namespace Grid {
namespace Providers {
namespace internal {

template< typename GridType >
struct ElementVariant;

template< typename GridType >
struct ElementVariant
{
  static const int id = 2;
};

template< int dim >
struct ElementVariant< Dune::YaspGrid< dim > >
{
  static const int id = 1;
};

template< int dim >
struct ElementVariant< Dune::SGrid< dim, dim > >
{
  static const int id = 1;
};

#if HAVE_ALUGRID

template< int dim >
struct ElementVariant< Dune::ALUCubeGrid< dim, dim > >
{
  static const int id = 1;
};

#endif // HAVE_ALUGRID

} // namespace internal

#if HAVE_DUNE_GRID

/**
 *  \brief  Creates a grid of a cube in various dimensions.
 *
 *          Default implementation using the Dune::StructuredGridFactory to create a grid of a cube in 1, 2 or 3
 *          dimensions. Tested with
 *

 \c YASPGRID, \c variant 1, dim = 1, 2, 3,
 *
 \c SGRID, \c variant 1, dim = 1, 2, 3,
 *
 \c ALUGRID_SIMPLEX, \c variant 2, dim = 2, 3,
 *
 \c ALUGRID_CONFORM, \c variant 2, dim = 2, 2 and
 *
 \c ALUGRID_CUBE, \c variant 1, dim = 2, 3.

 *  \tparam GridImp
 *          Type of the underlying grid.
 *  \tparam variant
 *          Type of the codim 0 elements:
 *

\c 1: cubes
 *
2: simplices

 **/
template< typename GridImp, int variant = internal::ElementVariant< GridImp >::id >
class Cube
  : public ProviderInterface< GridImp >
{
  typedef ProviderInterface< GridImp > BaseType;
  typedef Cube< GridImp, variant > ThisType;
public:
  using typename BaseType::GridType;
  static const unsigned int dimDomain = BaseType::dimDomain;
  using typename BaseType::DomainFieldType;
  using typename BaseType::DomainType;

  static const std::string static_id()
  {
    return BaseType::static_id() + ".cube";
  }

  virtual std::string id() /*DS_OVERRIDE*/
  {
    return BaseType::static_id() + ".cube";
  }

  /**
   *  \brief      Creates a cube.
   *  \param[in]  _lowerLeft
   *              A double that is used as a lower left corner in each dimension.
   *  \param[in]  _upperRight
   *              A double that is used as a upper right corner in each dimension.
   *  \param[in]  numElements (optional)
   *              number of elements.
   **/
  Cube(const double _lowerLeft = 0.0, const double _upperRight = 1.0, const unsigned int numElements = 1u)
    : lower_left_(_lowerLeft)
    , upper_right_(_upperRight)
  {
    std::array< unsigned int, dimDomain > tmpNumElements;
    std::fill(tmpNumElements.begin(), tmpNumElements.end(), numElements);
    buildGrid(tmpNumElements);
  }

  Cube(const std::vector< double >& lL, const std::vector< double >& uR, const std::vector< unsigned int >& nE)
  {
    if (lL.size() < dimDomain)
      DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                            "lL has to be at least of size " << dimDomain << " (is " << lL.size() << ")!");
    if (uR.size() < dimDomain)
      DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                            "uR has to be at least of size " << dimDomain << " (is " << uR.size() << ")!");
    if (nE.size() < dimDomain)
      DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                            "nE has to be at least of size " << dimDomain << " (is " << nE.size() << ")!");
    std::array< unsigned int, dimDomain > num_elements;
    for (unsigned int ii = 0; ii < dimDomain; ++ii) {
      lower_left_[ii] = lL[ii];
      upper_right_[ii] = uR[ii];
      num_elements[ii] = nE[ii];
    }
    buildGrid(num_elements);
  }

  /**
   *  \brief      Creates a cube.
   *  \param[in]  _lowerLeft
   *              A vector that is used as a lower left corner.
   *  \param[in]  _upperRight
   *              A vector that is used as a upper right corner.
   *  \param[in]  numElements (optional)
   *              number of elements.
   **/
  Cube(const DomainType& _lowerLeft, const DomainType& _upperRight, const unsigned int numElements = 1u)
    : lower_left_(_lowerLeft)
    , upper_right_(_upperRight)
  {
    std::array< unsigned int, dimDomain > tmpNumElements;
    std::fill(tmpNumElements.begin(), tmpNumElements.end(), numElements);
    buildGrid(tmpNumElements);
  }

  /**
    \brief      Creates a cube. This signature allows to prescribe anisotopic refinement
    \param[in]  _lowerLeft
                A double that is used as a lower left corner in each dimension.
    \param[in]  _upperRight
                A double that is used as a upper right corner in each dimension.
    \param[in]  numElements
                number of elements in each dimension.
                can contain 0 to dim elements (missing dimension are initialized to 1)
    \tparam ContainerType some sequence type that functions with std::begin/end
    **/
  template< class ContainerType  >
  Cube(const DomainType& _lowerLeft, const DomainType& _upperRight,
               const ContainerType numElements
                  = boost::assign::list_of< typename ContainerType::value_type>().repeat(dimDomain,
                                                                                typename ContainerType::value_type(1u)))
    : lower_left_(_lowerLeft),
      upper_right_(_upperRight)
  {
    std::array< unsigned int, dimDomain > tmpNumElements;
    static_assert(std::is_unsigned< typename ContainerType::value_type >::value
                  && std::is_integral< typename ContainerType::value_type >::value,
                  "only unsigned integral number of elements per dimension allowed");
    //base init in case input is shorter
    std::fill(tmpNumElements.begin(), tmpNumElements.end(), 1u);
    std::copy(numElements.begin(), numElements.end(), tmpNumElements.begin());
    buildGrid(tmpNumElements);
  }

  static ParameterTree default_config(const std::string sub_name = "")
  {
    Common::ConfigTree config;
    config["lower_left"] = "[0.0; 0.0; 0.0]";
    config["upper_right"] = "[1.0; 1.0; 1.0]";
    config["num_elements"] = "[8; 8; 8]";
    if (sub_name.empty())
      return config;
    else {
      Common::ConfigTree tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Common::ConfigTree config = default_config(),
                                            const std::string sub_name = static_id())
  {
    // get correct config
    Common::ConfigTree cfg;
    if (config.has_sub(sub_name))
      cfg = config.sub(sub_name);
    else
      cfg = config;
    // extract needed data
    try {
      // try to get vectors
      auto lower_left = cfg.get< DomainType >("lower_left", dimDomain);
      auto upper_right = cfg.get< DomainType >("upper_right", dimDomain);
      auto num_elements = cfg.get< std::vector< unsigned int > >("num_elements", dimDomain);
      return Common::make_unique< ThisType >(lower_left, upper_right, num_elements);
    } catch (Exceptions::configuration_error&) {
      // get scalars
      auto lower_left = cfg.get< DomainFieldType >("lower_left");
      auto upper_right = cfg.get< DomainFieldType >("upper_right");
      auto num_elements = cfg.get< unsigned int >("num_elements");
      return Common::make_unique< ThisType >(lower_left, upper_right, num_elements);
    }
  } // ... create(...)

  virtual std::shared_ptr< GridType >& grid() /*DS_OVERRIDE*/
  {
    return grid_;
  }

  virtual const std::shared_ptr< const GridType >& grid() const /*DS_OVERRIDE*/
  {
    return grid_;
  }

  const DomainType& lower_left() const
  {
    return lower_left_;
  }

  const DomainType& upper_right() const
  {
    return upper_right_;
  }

private:
  void buildGrid(const std::array< unsigned int, dimDomain >& numElements)
  {
    static_assert(variant == 1 || variant == 2, "variant has to be 1 or 2!");
    for (unsigned int dd = 0; dd < dimDomain; ++dd) {
      if (!(lower_left_[dd] < upper_right_[dd]))
        DUNE_THROW_COLORFULLY(Exceptions::wrong_input_given,
                              "lower_left has to be elementwise smaller than upper_right!\n\n"
                              << lower_left_[dd] << " vs. " << upper_right_[dd]);
    }
    switch (variant) {
      case 1:
        grid_ = Dune::StructuredGridFactory< GridType >::createCubeGrid(lower_left_, upper_right_, numElements);
        break;
      case 2:
    default:
        grid_ = Dune::StructuredGridFactory< GridType >::createSimplexGrid(lower_left_, upper_right_, numElements);
        break;
    }
  } // void buildGrid(const DomainType& lowerLeft, const DomainType& upperRight)

  DomainType lower_left_;
  DomainType upper_right_;
  std::shared_ptr< GridType > grid_;
}; // class Cube

#else // HAVE_DUNE_GRID

template< typename GridImp, int variant = 1 >
class Cube
{
  static_assert(AlwaysFalse< GridImp >::value, "You are missing dune-grid!");
};

#endif // HAVE_DUNE_GRID

} // namespace Providers
} // namespace Grid
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_GRIDS_PROVIDER_CUBE_HH
<|endoftext|>


<commit_before>#include <planet.h>
#include <planetsuniverse.h>
#include <chrono>

using namespace std::chrono;

int main() {
    PlanetsUniverse universe;

    /* Use a constant seed for consistency. */
    universe.randSeed(0);

    /* Test a thousand steps. */
    universe.stepsPerFrame = 1000;

    uint32_t sizes[] = { 20, 100, 500 };

    for (uint32_t size : sizes) {
        universe.generateRandom(size, 1000.0f, 1.0f, 1000.0f);

        printf("Simulating %i planets...\n", size);

        high_resolution_clock::time_point start = high_resolution_clock::now();

        universe.advance(10.0f);

        high_resolution_clock::time_point end = high_resolution_clock::now();

        auto delay = duration_cast<milliseconds>(end - start).count();

        printf("%i steps with %i planets took %ims, average step time: %fms.\n", universe.stepsPerFrame, size, delay, delay / float(universe.stepsPerFrame));
        printf("Ended with %i planets.\n", universe.size());

        fflush(stdout);

        /* Clear the thing for the next one. */
        universe.deleteAll();
    }

    return 0;
}
<commit_msg>Bench: fix issues with printf argument type mismatch.<commit_after>#include <planet.h>
#include <planetsuniverse.h>
#include <chrono>

using namespace std::chrono;

int main() {
    PlanetsUniverse universe;

    /* Use a constant seed for consistency. */
    universe.randSeed(0);

    /* Test a thousand steps. */
    universe.stepsPerFrame = 1000;

    size_t sizes[] = { 20, 100, 200, 500 };

    for (size_t size : sizes) {
        universe.generateRandom(size, 1000.0f, 1.0f, 1000.0f);

        printf("Simulating %zu planets...\n", size);

        high_resolution_clock::time_point start = high_resolution_clock::now();

        universe.advance(10.0f);

        high_resolution_clock::time_point end = high_resolution_clock::now();

        auto delay = duration_cast<milliseconds>(end - start).count();

        printf("%i steps with %zu planets took %lims, average step time: %fms.\n", universe.stepsPerFrame, size, delay, delay / float(universe.stepsPerFrame));
        printf("Ended with %zu planets.\n", universe.size());

        fflush(stdout);

        /* Clear the thing for the next one. */
        universe.deleteAll();
    }

    return 0;
}
<|endoftext|>


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

#include "InputFiles.h"
#include "InputSection.h"
#include "Error.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"

using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;

using namespace lld;
using namespace lld::elf2;

template <class ELFT> static uint16_t getEMachine(const ELFFileBase &B) {
  bool IsShared = isa<SharedFileBase>(B);
  if (IsShared)
    return cast<SharedFile<ELFT>>(B).getEMachine();
  return cast<ObjectFile<ELFT>>(B).getEMachine();
}

uint16_t ELFFileBase::getEMachine() const {
  switch (EKind) {
  case ELF32BEKind:
    return ::getEMachine<ELF32BE>(*this);
  case ELF32LEKind:
    return ::getEMachine<ELF32LE>(*this);
  case ELF64BEKind:
    return ::getEMachine<ELF64BE>(*this);
  case ELF64LEKind:
    return ::getEMachine<ELF64LE>(*this);
  }
  llvm_unreachable("Invalid kind");
}

bool ELFFileBase::isCompatibleWith(const ELFFileBase &Other) const {
  return getELFKind() == Other.getELFKind() &&
         getEMachine() == Other.getEMachine();
}

namespace {
class ECRAII {
  std::error_code EC;

public:
  std::error_code &getEC() { return EC; }
  ~ECRAII() { error(EC); }
};
}

template <class ELFT>
ELFData<ELFT>::ELFData(MemoryBufferRef MB)
    : ELFObj(MB.getBuffer(), ECRAII().getEC()) {}

template <class ELFT>
typename ELFData<ELFT>::Elf_Sym_Range
ELFData<ELFT>::getSymbolsHelper(bool Local) {
  if (!Symtab)
    return Elf_Sym_Range(nullptr, nullptr);
  Elf_Sym_Range Syms = ELFObj.symbols(Symtab);
  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
  uint32_t FirstNonLocal = Symtab->sh_info;
  if (FirstNonLocal > NumSymbols)
    error("Invalid sh_info in symbol table");
  if (!Local)
    return make_range(Syms.begin() + FirstNonLocal, Syms.end());
  // +1 to skip over dummy symbol.
  return make_range(Syms.begin() + 1, Syms.begin() + FirstNonLocal);
}

template <class ELFT>
typename ELFData<ELFT>::Elf_Sym_Range ELFData<ELFT>::getNonLocalSymbols() {
  if (!Symtab)
    return Elf_Sym_Range(nullptr, nullptr);
  ErrorOr<StringRef> StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab);
  error(StringTableOrErr.getError());
  StringTable = *StringTableOrErr;
  return getSymbolsHelper(false);
}

template <class ELFT>
ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
    : ObjectFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}

template <class ELFT>
typename ObjectFile<ELFT>::Elf_Sym_Range ObjectFile<ELFT>::getLocalSymbols() {
  return this->getSymbolsHelper(true);
}

template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
  // Read section and symbol tables.
  initializeSections();
  initializeSymbols();
}

template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSections() {
  uint64_t Size = this->ELFObj.getNumSections();
  Sections.resize(Size);
  unsigned I = 0;
  for (const Elf_Shdr &Sec : this->ELFObj.sections()) {
    switch (Sec.sh_type) {
    case SHT_SYMTAB:
      this->Symtab = &Sec;
      break;
    case SHT_SYMTAB_SHNDX: {
      ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable =
          this->ELFObj.getSHNDXTable(Sec);
      error(ErrorOrTable);
      SymtabSHNDX = *ErrorOrTable;
      break;
    }
    case SHT_STRTAB:
    case SHT_NULL:
      break;
    case SHT_RELA:
    case SHT_REL: {
      uint32_t RelocatedSectionIndex = Sec.sh_info;
      if (RelocatedSectionIndex >= Size)
        error("Invalid relocated section index");
      InputSection<ELFT> *RelocatedSection = Sections[RelocatedSectionIndex];
      if (!RelocatedSection)
        error("Unsupported relocation reference");
      RelocatedSection->RelocSections.push_back(&Sec);
      break;
    }
    default:
      Sections[I] = new (Alloc) InputSection<ELFT>(this, &Sec);
      break;
    }
    ++I;
  }
}

template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
  Elf_Sym_Range Syms = this->getNonLocalSymbols();
  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
  SymbolBodies.reserve(NumSymbols);
  for (const Elf_Sym &Sym : Syms)
    SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
}

template <class ELFT>
SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
                                                     const Elf_Sym *Sym) {
  ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
  error(NameOrErr.getError());
  StringRef Name = *NameOrErr;

  uint32_t SecIndex = Sym->st_shndx;
  switch (SecIndex) {
  case SHN_ABS:
    return new (Alloc) DefinedAbsolute<ELFT>(Name, *Sym);
  case SHN_UNDEF:
    return new (Alloc) Undefined<ELFT>(Name, *Sym);
  case SHN_COMMON:
    return new (Alloc) DefinedCommon<ELFT>(Name, *Sym);
  case SHN_XINDEX:
    SecIndex = this->ELFObj.getExtendedSymbolTableIndex(Sym, this->Symtab,
                                                        SymtabSHNDX);
    break;
  }

  if (SecIndex >= Sections.size() || (SecIndex != 0 && !Sections[SecIndex]))
    error("Invalid section index");

  switch (Sym->getBinding()) {
  default:
    error("unexpected binding");
  case STB_GLOBAL:
  case STB_WEAK:
    return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Sections[SecIndex]);
  }
}

void ArchiveFile::parse() {
  auto ArchiveOrErr = Archive::create(MB);
  error(ArchiveOrErr, "Failed to parse archive");
  File = std::move(*ArchiveOrErr);

  // Allocate a buffer for Lazy objects.
  size_t NumSyms = File->getNumberOfSymbols();
  LazySymbols.reserve(NumSyms);

  // Read the symbol table to construct Lazy objects.
  for (const Archive::Symbol &Sym : File->symbols())
    LazySymbols.emplace_back(this, Sym);
}

// Returns a buffer pointing to a member file containing a given symbol.
MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
  ErrorOr<Archive::child_iterator> ItOrErr = Sym->getMember();
  error(ItOrErr,
        Twine("Could not get the member for symbol ") + Sym->getName());
  Archive::child_iterator It = *ItOrErr;

  if (!Seen.insert(It->getChildOffset()).second)
    return MemoryBufferRef();

  ErrorOr<MemoryBufferRef> Ret = It->getMemoryBufferRef();
  error(Ret, Twine("Could not get the buffer for the member defining symbol ") +
                 Sym->getName());
  return *Ret;
}

template <class ELFT>
SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
    : SharedFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}

template <class ELFT> void SharedFile<ELFT>::parse() {
  for (const Elf_Shdr &Sec : this->ELFObj.sections()) {
    if (Sec.sh_type == SHT_DYNSYM) {
      this->Symtab = &Sec;
      break;
    }
  }

  Elf_Sym_Range Syms = this->getNonLocalSymbols();
  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
  SymbolBodies.reserve(NumSymbols);
  for (const Elf_Sym &Sym : Syms) {
    if (Sym.isUndefined())
      continue;

    ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
    error(NameOrErr.getError());
    StringRef Name = *NameOrErr;

    SymbolBodies.emplace_back(Name, Sym);
  }
}

namespace lld {
namespace elf2 {

template class elf2::ObjectFile<llvm::object::ELF32LE>;
template class elf2::ObjectFile<llvm::object::ELF32BE>;
template class elf2::ObjectFile<llvm::object::ELF64LE>;
template class elf2::ObjectFile<llvm::object::ELF64BE>;

template class elf2::SharedFile<llvm::object::ELF32LE>;
template class elf2::SharedFile<llvm::object::ELF32BE>;
template class elf2::SharedFile<llvm::object::ELF64LE>;
template class elf2::SharedFile<llvm::object::ELF64BE>;
}
}
<commit_msg>Expand `auto` whose real type is not obvious from context.<commit_after>//===- InputFiles.cpp -----------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "InputFiles.h"
#include "InputSection.h"
#include "Error.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"

using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;

using namespace lld;
using namespace lld::elf2;

template <class ELFT> static uint16_t getEMachine(const ELFFileBase &B) {
  bool IsShared = isa<SharedFileBase>(B);
  if (IsShared)
    return cast<SharedFile<ELFT>>(B).getEMachine();
  return cast<ObjectFile<ELFT>>(B).getEMachine();
}

uint16_t ELFFileBase::getEMachine() const {
  switch (EKind) {
  case ELF32BEKind:
    return ::getEMachine<ELF32BE>(*this);
  case ELF32LEKind:
    return ::getEMachine<ELF32LE>(*this);
  case ELF64BEKind:
    return ::getEMachine<ELF64BE>(*this);
  case ELF64LEKind:
    return ::getEMachine<ELF64LE>(*this);
  }
  llvm_unreachable("Invalid kind");
}

bool ELFFileBase::isCompatibleWith(const ELFFileBase &Other) const {
  return getELFKind() == Other.getELFKind() &&
         getEMachine() == Other.getEMachine();
}

namespace {
class ECRAII {
  std::error_code EC;

public:
  std::error_code &getEC() { return EC; }
  ~ECRAII() { error(EC); }
};
}

template <class ELFT>
ELFData<ELFT>::ELFData(MemoryBufferRef MB)
    : ELFObj(MB.getBuffer(), ECRAII().getEC()) {}

template <class ELFT>
typename ELFData<ELFT>::Elf_Sym_Range
ELFData<ELFT>::getSymbolsHelper(bool Local) {
  if (!Symtab)
    return Elf_Sym_Range(nullptr, nullptr);
  Elf_Sym_Range Syms = ELFObj.symbols(Symtab);
  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
  uint32_t FirstNonLocal = Symtab->sh_info;
  if (FirstNonLocal > NumSymbols)
    error("Invalid sh_info in symbol table");
  if (!Local)
    return make_range(Syms.begin() + FirstNonLocal, Syms.end());
  // +1 to skip over dummy symbol.
  return make_range(Syms.begin() + 1, Syms.begin() + FirstNonLocal);
}

template <class ELFT>
typename ELFData<ELFT>::Elf_Sym_Range ELFData<ELFT>::getNonLocalSymbols() {
  if (!Symtab)
    return Elf_Sym_Range(nullptr, nullptr);
  ErrorOr<StringRef> StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab);
  error(StringTableOrErr.getError());
  StringTable = *StringTableOrErr;
  return getSymbolsHelper(false);
}

template <class ELFT>
ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
    : ObjectFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}

template <class ELFT>
typename ObjectFile<ELFT>::Elf_Sym_Range ObjectFile<ELFT>::getLocalSymbols() {
  return this->getSymbolsHelper(true);
}

template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
  // Read section and symbol tables.
  initializeSections();
  initializeSymbols();
}

template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSections() {
  uint64_t Size = this->ELFObj.getNumSections();
  Sections.resize(Size);
  unsigned I = 0;
  for (const Elf_Shdr &Sec : this->ELFObj.sections()) {
    switch (Sec.sh_type) {
    case SHT_SYMTAB:
      this->Symtab = &Sec;
      break;
    case SHT_SYMTAB_SHNDX: {
      ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable =
          this->ELFObj.getSHNDXTable(Sec);
      error(ErrorOrTable);
      SymtabSHNDX = *ErrorOrTable;
      break;
    }
    case SHT_STRTAB:
    case SHT_NULL:
      break;
    case SHT_RELA:
    case SHT_REL: {
      uint32_t RelocatedSectionIndex = Sec.sh_info;
      if (RelocatedSectionIndex >= Size)
        error("Invalid relocated section index");
      InputSection<ELFT> *RelocatedSection = Sections[RelocatedSectionIndex];
      if (!RelocatedSection)
        error("Unsupported relocation reference");
      RelocatedSection->RelocSections.push_back(&Sec);
      break;
    }
    default:
      Sections[I] = new (Alloc) InputSection<ELFT>(this, &Sec);
      break;
    }
    ++I;
  }
}

template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
  Elf_Sym_Range Syms = this->getNonLocalSymbols();
  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
  SymbolBodies.reserve(NumSymbols);
  for (const Elf_Sym &Sym : Syms)
    SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
}

template <class ELFT>
SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
                                                     const Elf_Sym *Sym) {
  ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
  error(NameOrErr.getError());
  StringRef Name = *NameOrErr;

  uint32_t SecIndex = Sym->st_shndx;
  switch (SecIndex) {
  case SHN_ABS:
    return new (Alloc) DefinedAbsolute<ELFT>(Name, *Sym);
  case SHN_UNDEF:
    return new (Alloc) Undefined<ELFT>(Name, *Sym);
  case SHN_COMMON:
    return new (Alloc) DefinedCommon<ELFT>(Name, *Sym);
  case SHN_XINDEX:
    SecIndex = this->ELFObj.getExtendedSymbolTableIndex(Sym, this->Symtab,
                                                        SymtabSHNDX);
    break;
  }

  if (SecIndex >= Sections.size() || (SecIndex != 0 && !Sections[SecIndex]))
    error("Invalid section index");

  switch (Sym->getBinding()) {
  default:
    error("unexpected binding");
  case STB_GLOBAL:
  case STB_WEAK:
    return new (Alloc) DefinedRegular<ELFT>(Name, *Sym, *Sections[SecIndex]);
  }
}

void ArchiveFile::parse() {
  ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB);
  error(ArchiveOrErr, "Failed to parse archive");
  File = std::move(*ArchiveOrErr);

  // Allocate a buffer for Lazy objects.
  size_t NumSyms = File->getNumberOfSymbols();
  LazySymbols.reserve(NumSyms);

  // Read the symbol table to construct Lazy objects.
  for (const Archive::Symbol &Sym : File->symbols())
    LazySymbols.emplace_back(this, Sym);
}

// Returns a buffer pointing to a member file containing a given symbol.
MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
  ErrorOr<Archive::child_iterator> ItOrErr = Sym->getMember();
  error(ItOrErr,
        Twine("Could not get the member for symbol ") + Sym->getName());
  Archive::child_iterator It = *ItOrErr;

  if (!Seen.insert(It->getChildOffset()).second)
    return MemoryBufferRef();

  ErrorOr<MemoryBufferRef> Ret = It->getMemoryBufferRef();
  error(Ret, Twine("Could not get the buffer for the member defining symbol ") +
                 Sym->getName());
  return *Ret;
}

template <class ELFT>
SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
    : SharedFileBase(getStaticELFKind<ELFT>(), M), ELFData<ELFT>(M) {}

template <class ELFT> void SharedFile<ELFT>::parse() {
  for (const Elf_Shdr &Sec : this->ELFObj.sections()) {
    if (Sec.sh_type == SHT_DYNSYM) {
      this->Symtab = &Sec;
      break;
    }
  }

  Elf_Sym_Range Syms = this->getNonLocalSymbols();
  uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
  SymbolBodies.reserve(NumSymbols);
  for (const Elf_Sym &Sym : Syms) {
    if (Sym.isUndefined())
      continue;

    ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
    error(NameOrErr.getError());
    StringRef Name = *NameOrErr;

    SymbolBodies.emplace_back(Name, Sym);
  }
}

namespace lld {
namespace elf2 {

template class elf2::ObjectFile<llvm::object::ELF32LE>;
template class elf2::ObjectFile<llvm::object::ELF32BE>;
template class elf2::ObjectFile<llvm::object::ELF64LE>;
template class elf2::ObjectFile<llvm::object::ELF64BE>;

template class elf2::SharedFile<llvm::object::ELF32LE>;
template class elf2::SharedFile<llvm::object::ELF32BE>;
template class elf2::SharedFile<llvm::object::ELF64LE>;
template class elf2::SharedFile<llvm::object::ELF64BE>;
}
}
<|endoftext|>