<commit_before>//===- gccld.cpp - LLVM 'ld' compatible linker ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility is intended to be compatible with GCC, and follows standard
// system 'ld' conventions.  As such, the default output file is ./a.out.
// Additionally, this program outputs a shell script that is used to invoke LLI
// to execute the program.  In this manner, the generated executable (a.out for
// example), is directly executable, whereas the bytecode file actually lives in
// the a.out.bc file generated by this program.  Also, Force is on by default.
//
// Note that if someone (or a script) deletes the executable program generated,
// the .bc file will be left around.  Considering that this is a temporary hack,
// I'm not too worried about this.
//
//===----------------------------------------------------------------------===//

#include "gccld.h"
#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/System/Signals.h"
#include "llvm/Support/SystemUtils.h"
#include <fstream>
#include <memory>
using namespace llvm;

namespace {
  cl::list<std::string>
  InputFilenames(cl::Positional, cl::desc("<input bytecode files>"),
                 cl::OneOrMore);

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"),
                 cl::value_desc("filename"));

  cl::opt<bool>
  Verbose("v", cl::desc("Print information about actions taken"));

  cl::list<std::string>
  LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix,
           cl::value_desc("directory"));

  cl::list<std::string>
  Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix,
            cl::value_desc("library prefix"));

  cl::opt<bool>
  Strip("strip-all", cl::desc("Strip all symbol info from executable"));
  cl::opt<bool>
  StripDebug("strip-debug",
             cl::desc("Strip debugger symbol info from executable"));

  cl::opt<bool>
  NoInternalize("disable-internalize",
                cl::desc("Do not mark all symbols as internal"));
  cl::alias
  ExportDynamic("export-dynamic", cl::desc("Alias for -disable-internalize"),
                cl::aliasopt(NoInternalize));

  cl::opt<bool>
  LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a"
                                            " library, not an executable"));
  cl::alias
  Relink("r", cl::desc("Alias for -link-as-library"),
         cl::aliasopt(LinkAsLibrary));

  cl::opt<bool>
  Native("native",
         cl::desc("Generate a native binary instead of a shell script"));
  cl::opt<bool>
  NativeCBE("native-cbe",
            cl::desc("Generate a native binary with the C backend and GCC"));

  // Compatibility options that are ignored but supported by LD
  cl::opt<std::string>
  CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored"));
  cl::opt<std::string>
  CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored"));
  cl::opt<bool>
  CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored"));
  cl::opt<std::string>
  CO6("h", cl::Hidden, cl::desc("Compatibility option: ignored"));

  cl::alias A0("s", cl::desc("Alias for --strip-all"),
               cl::aliasopt(Strip));
  cl::alias A1("S", cl::desc("Alias for --strip-debug"),
               cl::aliasopt(StripDebug));
}

/// PrintAndReturn - Prints a message to standard error and returns true.
///
/// Inputs:
///  progname - The name of the program (i.e. argv[0]).
///  Message  - The message to print to standard error.
///
static int PrintAndReturn(const char *progname, const std::string &Message) {
  std::cerr << progname << ": " << Message << "\n";
  return 1;
}

/// EmitShellScript - Output the wrapper file that invokes the JIT on the LLVM
/// bytecode file for the program.
static void EmitShellScript(char **argv) {
#if defined(_WIN32) || defined(__CYGWIN__)
  // Windows doesn't support #!/bin/sh style shell scripts in .exe files.  To
  // support windows systems, we copy the llvm-stub.exe executable from the
  // build tree to the destination file.
  std::string llvmstub = FindExecutable("llvm-stub.exe", argv[0]);
  if (llvmstub.empty()) {
    std::cerr << "Could not find llvm-stub.exe executable!\n";
    exit(1);
  }
  if (CopyFile(OutputFilename, llvmstub)) {
    std::cerr << "Could not copy the llvm-stub.exe executable!\n";
    exit(1);
  }
  return;
#endif

  // Output the script to start the program...
  std::ofstream Out2(OutputFilename.c_str());
  if (!Out2.good())
    exit(PrintAndReturn(argv[0], "error opening '" + OutputFilename +
                                 "' for writing!"));

  Out2 << "#!/bin/sh\n";
  // Allow user to setenv LLVMINTERP if lli is not in their PATH.
  Out2 << "lli=${LLVMINTERP-lli}\n";
  Out2 << "exec $lli \\\n";
  // gcc accepts -l<lib> and implicitly searches /lib and /usr/lib.
  LibPaths.push_back("/lib");
  LibPaths.push_back("/usr/lib");
  LibPaths.push_back("/usr/X11R6/lib");
  // We don't need to link in libc! In fact, /usr/lib/libc.so may not be a
  // shared object at all! See RH 8: plain text.
  std::vector<std::string>::iterator libc =
    std::find(Libraries.begin(), Libraries.end(), "c");
  if (libc != Libraries.end()) Libraries.erase(libc);
  // List all the shared object (native) libraries this executable will need
  // on the command line, so that we don't have to do this manually!
  for (std::vector<std::string>::iterator i = Libraries.begin(),
         e = Libraries.end(); i != e; ++i) {
    std::string FullLibraryPath = FindLib(*i, LibPaths, true);
    if (!FullLibraryPath.empty() && IsSharedObject(FullLibraryPath))
      Out2 << "    -load=" << FullLibraryPath << " \\\n";
  }
  Out2 << "    $0.bc ${1+\"$@\"}\n";
  Out2.close();
}

int main(int argc, char **argv, char **envp) {
  cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n");
  sys::PrintStackTraceOnErrorSignal();

  int exitCode = 0;

  try {
    // Remove any consecutive duplicates of the same library...
    Libraries.erase(std::unique(Libraries.begin(), Libraries.end()),
                    Libraries.end());

    // Set up the Composite module.
    std::auto_ptr<Module> Composite(0);

    if (LinkAsLibrary) {
      // Link in only the files.
      Composite.reset( new Module(argv[0]) );
      if (LinkFiles(argv[0], Composite.get(), InputFilenames, Verbose))
        return 1; // Error already printed
      // The libraries aren't linked in but are noted as "dependent" in the
      // module.
      for (cl::list<std::string>::const_iterator I = Libraries.begin(),
           E = Libraries.end(); I != E ; ++I) {
        Composite.get()->addLibrary(*I);
      }

    } else {
      // Build a list of the items from our command line
      LinkItemList Items;
      BuildLinkItems(Items, InputFilenames, Libraries);

      // Link all the items together
      Composite.reset( LinkItems(argv[0], Items, LibPaths, Verbose, Native) );

      // Check for an error during linker
      if (!Composite.get())
        return 1; // Error already printed
    }

    // Create the output file.
    std::string RealBytecodeOutput = OutputFilename;
    if (!LinkAsLibrary) RealBytecodeOutput += ".bc";
    std::ofstream Out(RealBytecodeOutput.c_str());
    if (!Out.good())
      return PrintAndReturn(argv[0], "error opening '" + RealBytecodeOutput +
                                     "' for writing!");

    // Ensure that the bytecode file gets removed from the disk if we get a
    // SIGINT signal.
    sys::RemoveFileOnSignal(sys::Path(RealBytecodeOutput));

    // Generate the bytecode file.
    int StripLevel = Strip ? 2 : (StripDebug ? 1 : 0);
    if (GenerateBytecode(Composite.get(), StripLevel, !NoInternalize, &Out)) {
      Out.close();
      return PrintAndReturn(argv[0], "error generating bytecode");
    }

    // Close the bytecode file.
    Out.close();

    // If we are not linking a library, generate either a native executable
    // or a JIT shell script, depending upon what the user wants.
    if (!LinkAsLibrary) {
      // If the user wants to generate a native executable, compile it from the
      // bytecode file.
      //
      // Otherwise, create a script that will run the bytecode through the JIT.
      if (Native) {
        // Name of the Assembly Language output file
        std::string AssemblyFile = OutputFilename + ".s";

        // Mark the output files for removal if we get an interrupt.
        sys::RemoveFileOnSignal(sys::Path(AssemblyFile));
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));

        // Determine the locations of the llc and gcc programs.
        std::string llc = FindExecutable("llc", argv[0]);
        std::string gcc = FindExecutable("gcc", argv[0]);
        if (llc.empty())
          return PrintAndReturn(argv[0], "Failed to find llc");

        if (gcc.empty())
          return PrintAndReturn(argv[0], "Failed to find gcc");

        // Generate an assembly language file for the bytecode.
        if (Verbose) std::cout << "Generating Assembly Code\n";
        GenerateAssembly(AssemblyFile, RealBytecodeOutput, llc, envp);
        if (Verbose) std::cout << "Generating Native Code\n";
        GenerateNative(OutputFilename, AssemblyFile, Libraries, LibPaths,
                       gcc, envp);

        // Remove the assembly language file.
        removeFile (AssemblyFile);
      } else if (NativeCBE) {
        std::string CFile = OutputFilename + ".cbe.c";

        // Mark the output files for removal if we get an interrupt.
        sys::RemoveFileOnSignal(sys::Path(CFile));
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));

        // Determine the locations of the llc and gcc programs.
        std::string llc = FindExecutable("llc", argv[0]);
        std::string gcc = FindExecutable("gcc", argv[0]);
        if (llc.empty())
          return PrintAndReturn(argv[0], "Failed to find llc");
        if (gcc.empty())
          return PrintAndReturn(argv[0], "Failed to find gcc");

        // Generate an assembly language file for the bytecode.
        if (Verbose) std::cout << "Generating Assembly Code\n";
        GenerateCFile(CFile, RealBytecodeOutput, llc, envp);
        if (Verbose) std::cout << "Generating Native Code\n";
        GenerateNative(OutputFilename, CFile, Libraries, LibPaths, gcc, envp);

        // Remove the assembly language file.
        removeFile(CFile);

      } else {
        EmitShellScript(argv);
      }

      // Make the script executable...
      MakeFileExecutable(OutputFilename);

      // Make the bytecode file readable and directly executable in LLEE as well
      MakeFileExecutable(RealBytecodeOutput);
      MakeFileReadable(RealBytecodeOutput);
    }
  } catch (const char*msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
    exitCode = 1;
  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
    exitCode = 2;
  } catch (...) {
    // This really shouldn't happen, but just in case ....
    std::cerr << argv[0] << ": An nexpected unknown exception occurred.\n";
    exitCode = 3;
  }

  return exitCode;
}
<commit_msg>Do not internalize a module if -link-as-library is passed.<commit_after>//===- gccld.cpp - LLVM 'ld' compatible linker ----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This utility is intended to be compatible with GCC, and follows standard
// system 'ld' conventions.  As such, the default output file is ./a.out.
// Additionally, this program outputs a shell script that is used to invoke LLI
// to execute the program.  In this manner, the generated executable (a.out for
// example), is directly executable, whereas the bytecode file actually lives in
// the a.out.bc file generated by this program.  Also, Force is on by default.
//
// Note that if someone (or a script) deletes the executable program generated,
// the .bc file will be left around.  Considering that this is a temporary hack,
// I'm not too worried about this.
//
//===----------------------------------------------------------------------===//

#include "gccld.h"
#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/System/Signals.h"
#include "llvm/Support/SystemUtils.h"
#include <fstream>
#include <memory>
using namespace llvm;

namespace {
  cl::list<std::string>
  InputFilenames(cl::Positional, cl::desc("<input bytecode files>"),
                 cl::OneOrMore);

  cl::opt<std::string>
  OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"),
                 cl::value_desc("filename"));

  cl::opt<bool>
  Verbose("v", cl::desc("Print information about actions taken"));

  cl::list<std::string>
  LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix,
           cl::value_desc("directory"));

  cl::list<std::string>
  Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix,
            cl::value_desc("library prefix"));

  cl::opt<bool>
  Strip("strip-all", cl::desc("Strip all symbol info from executable"));
  cl::opt<bool>
  StripDebug("strip-debug",
             cl::desc("Strip debugger symbol info from executable"));

  cl::opt<bool>
  NoInternalize("disable-internalize",
                cl::desc("Do not mark all symbols as internal"));
  cl::alias
  ExportDynamic("export-dynamic", cl::desc("Alias for -disable-internalize"),
                cl::aliasopt(NoInternalize));

  cl::opt<bool>
  LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a"
                                            " library, not an executable"));
  cl::alias
  Relink("r", cl::desc("Alias for -link-as-library"),
         cl::aliasopt(LinkAsLibrary));

  cl::opt<bool>
  Native("native",
         cl::desc("Generate a native binary instead of a shell script"));
  cl::opt<bool>
  NativeCBE("native-cbe",
            cl::desc("Generate a native binary with the C backend and GCC"));

  // Compatibility options that are ignored but supported by LD
  cl::opt<std::string>
  CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored"));
  cl::opt<std::string>
  CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored"));
  cl::opt<bool>
  CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored"));
  cl::opt<std::string>
  CO6("h", cl::Hidden, cl::desc("Compatibility option: ignored"));

  cl::alias A0("s", cl::desc("Alias for --strip-all"),
               cl::aliasopt(Strip));
  cl::alias A1("S", cl::desc("Alias for --strip-debug"),
               cl::aliasopt(StripDebug));
}

/// PrintAndReturn - Prints a message to standard error and returns true.
///
/// Inputs:
///  progname - The name of the program (i.e. argv[0]).
///  Message  - The message to print to standard error.
///
static int PrintAndReturn(const char *progname, const std::string &Message) {
  std::cerr << progname << ": " << Message << "\n";
  return 1;
}

/// EmitShellScript - Output the wrapper file that invokes the JIT on the LLVM
/// bytecode file for the program.
static void EmitShellScript(char **argv) {
#if defined(_WIN32) || defined(__CYGWIN__)
  // Windows doesn't support #!/bin/sh style shell scripts in .exe files.  To
  // support windows systems, we copy the llvm-stub.exe executable from the
  // build tree to the destination file.
  std::string llvmstub = FindExecutable("llvm-stub.exe", argv[0]);
  if (llvmstub.empty()) {
    std::cerr << "Could not find llvm-stub.exe executable!\n";
    exit(1);
  }
  if (CopyFile(OutputFilename, llvmstub)) {
    std::cerr << "Could not copy the llvm-stub.exe executable!\n";
    exit(1);
  }
  return;
#endif

  // Output the script to start the program...
  std::ofstream Out2(OutputFilename.c_str());
  if (!Out2.good())
    exit(PrintAndReturn(argv[0], "error opening '" + OutputFilename +
                                 "' for writing!"));

  Out2 << "#!/bin/sh\n";
  // Allow user to setenv LLVMINTERP if lli is not in their PATH.
  Out2 << "lli=${LLVMINTERP-lli}\n";
  Out2 << "exec $lli \\\n";
  // gcc accepts -l<lib> and implicitly searches /lib and /usr/lib.
  LibPaths.push_back("/lib");
  LibPaths.push_back("/usr/lib");
  LibPaths.push_back("/usr/X11R6/lib");
  // We don't need to link in libc! In fact, /usr/lib/libc.so may not be a
  // shared object at all! See RH 8: plain text.
  std::vector<std::string>::iterator libc =
    std::find(Libraries.begin(), Libraries.end(), "c");
  if (libc != Libraries.end()) Libraries.erase(libc);
  // List all the shared object (native) libraries this executable will need
  // on the command line, so that we don't have to do this manually!
  for (std::vector<std::string>::iterator i = Libraries.begin(),
         e = Libraries.end(); i != e; ++i) {
    std::string FullLibraryPath = FindLib(*i, LibPaths, true);
    if (!FullLibraryPath.empty() && IsSharedObject(FullLibraryPath))
      Out2 << "    -load=" << FullLibraryPath << " \\\n";
  }
  Out2 << "    $0.bc ${1+\"$@\"}\n";
  Out2.close();
}

int main(int argc, char **argv, char **envp) {
  cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n");
  sys::PrintStackTraceOnErrorSignal();

  int exitCode = 0;

  try {
    // Remove any consecutive duplicates of the same library...
    Libraries.erase(std::unique(Libraries.begin(), Libraries.end()),
                    Libraries.end());

    // Set up the Composite module.
    std::auto_ptr<Module> Composite(0);

    if (LinkAsLibrary) {
      // Link in only the files.
      Composite.reset( new Module(argv[0]) );
      if (LinkFiles(argv[0], Composite.get(), InputFilenames, Verbose))
        return 1; // Error already printed
      // The libraries aren't linked in but are noted as "dependent" in the
      // module.
      for (cl::list<std::string>::const_iterator I = Libraries.begin(),
           E = Libraries.end(); I != E ; ++I) {
        Composite.get()->addLibrary(*I);
      }

    } else {
      // Build a list of the items from our command line
      LinkItemList Items;
      BuildLinkItems(Items, InputFilenames, Libraries);

      // Link all the items together
      Composite.reset( LinkItems(argv[0], Items, LibPaths, Verbose, Native) );

      // Check for an error during linker
      if (!Composite.get())
        return 1; // Error already printed
    }

    // Create the output file.
    std::string RealBytecodeOutput = OutputFilename;
    if (!LinkAsLibrary) RealBytecodeOutput += ".bc";
    std::ofstream Out(RealBytecodeOutput.c_str());
    if (!Out.good())
      return PrintAndReturn(argv[0], "error opening '" + RealBytecodeOutput +
                                     "' for writing!");

    // Ensure that the bytecode file gets removed from the disk if we get a
    // SIGINT signal.
    sys::RemoveFileOnSignal(sys::Path(RealBytecodeOutput));

    // Strip everything if Strip is set, otherwise if stripdebug is set, just
    // strip debug info.
    int StripLevel = Strip ? 2 : (StripDebug ? 1 : 0);

    // Internalize the module if neither -disable-internalize nor
    // -link-as-library are passed in.
    bool ShouldInternalize = !NoInternalize & !LinkAsLibrary;

    // Generate the bytecode file.
    if (GenerateBytecode(Composite.get(), StripLevel, ShouldInternalize, &Out)){
      Out.close();
      return PrintAndReturn(argv[0], "error generating bytecode");
    }

    // Close the bytecode file.
    Out.close();

    // If we are not linking a library, generate either a native executable
    // or a JIT shell script, depending upon what the user wants.
    if (!LinkAsLibrary) {
      // If the user wants to generate a native executable, compile it from the
      // bytecode file.
      //
      // Otherwise, create a script that will run the bytecode through the JIT.
      if (Native) {
        // Name of the Assembly Language output file
        std::string AssemblyFile = OutputFilename + ".s";

        // Mark the output files for removal if we get an interrupt.
        sys::RemoveFileOnSignal(sys::Path(AssemblyFile));
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));

        // Determine the locations of the llc and gcc programs.
        std::string llc = FindExecutable("llc", argv[0]);
        std::string gcc = FindExecutable("gcc", argv[0]);
        if (llc.empty())
          return PrintAndReturn(argv[0], "Failed to find llc");

        if (gcc.empty())
          return PrintAndReturn(argv[0], "Failed to find gcc");

        // Generate an assembly language file for the bytecode.
        if (Verbose) std::cout << "Generating Assembly Code\n";
        GenerateAssembly(AssemblyFile, RealBytecodeOutput, llc, envp);
        if (Verbose) std::cout << "Generating Native Code\n";
        GenerateNative(OutputFilename, AssemblyFile, Libraries, LibPaths,
                       gcc, envp);

        // Remove the assembly language file.
        removeFile (AssemblyFile);
      } else if (NativeCBE) {
        std::string CFile = OutputFilename + ".cbe.c";

        // Mark the output files for removal if we get an interrupt.
        sys::RemoveFileOnSignal(sys::Path(CFile));
        sys::RemoveFileOnSignal(sys::Path(OutputFilename));

        // Determine the locations of the llc and gcc programs.
        std::string llc = FindExecutable("llc", argv[0]);
        std::string gcc = FindExecutable("gcc", argv[0]);
        if (llc.empty())
          return PrintAndReturn(argv[0], "Failed to find llc");
        if (gcc.empty())
          return PrintAndReturn(argv[0], "Failed to find gcc");

        // Generate an assembly language file for the bytecode.
        if (Verbose) std::cout << "Generating Assembly Code\n";
        GenerateCFile(CFile, RealBytecodeOutput, llc, envp);
        if (Verbose) std::cout << "Generating Native Code\n";
        GenerateNative(OutputFilename, CFile, Libraries, LibPaths, gcc, envp);

        // Remove the assembly language file.
        removeFile(CFile);

      } else {
        EmitShellScript(argv);
      }

      // Make the script executable...
      MakeFileExecutable(OutputFilename);

      // Make the bytecode file readable and directly executable in LLEE as well
      MakeFileExecutable(RealBytecodeOutput);
      MakeFileReadable(RealBytecodeOutput);
    }
  } catch (const char*msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
    exitCode = 1;
  } catch (const std::string& msg) {
    std::cerr << argv[0] << ": " << msg << "\n";
    exitCode = 2;
  } catch (...) {
    // This really shouldn't happen, but just in case ....
    std::cerr << argv[0] << ": An nexpected unknown exception occurred.\n";
    exitCode = 3;
  }

  return exitCode;
}
<|endoftext|>


<commit_before><commit_msg>uses the executioncontext defined stream for output<commit_after><|endoftext|>


<commit_before>#include "LetterAssembler.hpp"

#include <algorithm>
#include <set>
#include <tuple>

bool LetterAssembler::read(std::istream &inputStream) {
  auto pairCount = 0u;
  auto sumFirstWordLength = 0ul;
  auto sumSecondWordLength = 0ul;
  this->wordPairs.clear();

  inputStream >> pairCount;

  if (pairCount == 0) {
    return false;
  }

  this->wordPairs.reserve(pairCount);

  for (size_t pos = 0; pos < pairCount; ++pos) {
    std::string firstWord;
    std::string secondWord;

    inputStream >> firstWord >> secondWord;

    sumFirstWordLength += firstWord.length();
    sumSecondWordLength += secondWord.length();

    this->wordPairs.push_back(std::make_pair(std::move(firstWord), std::move(secondWord)));
  }

  inputStream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  std::sort(this->wordPairs.begin(), wordPairs.end());
  this->maximumPossibleLength = std::min(sumFirstWordLength, sumSecondWordLength);

  return true;
}

std::string LetterAssembler::assemble() {
  AssemblerState state;
  state.firstLetter.reserve(maximumPossibleLength);
  state.secondLetter.reserve(maximumPossibleLength);
  state.used = std::vector<bool>(this->wordPairs.size(), false);
  this->recursiveSearch(state);
  if (state.best.empty()) {
    return "IMPOSSIBLE";
  } else {
    return state.best;
  }
}

void LetterAssembler::recursiveSearch(AssemblerState &state) {
  auto actualPos = std::min(state.firstLetter.length(), state.secondLetter.length());
  for (auto i = 0u; i < this->wordPairs.size(); ++i) {
    if (!state.used[i]) {
      state.used[i] = true;
      const auto &firstWord = this->wordPairs[i].first;
      const auto &secondWord = this->wordPairs[i].second;
      state.firstLetter.append(firstWord);
      state.secondLetter.append(secondWord);
      auto endPos = std::min(state.firstLetter.length(), state.secondLetter.length());
      auto isGoodContinuation =
          std::equal(&state.firstLetter[actualPos], &state.firstLetter[endPos], &state.secondLetter[actualPos]);
      if (isGoodContinuation) {
        if (state.firstLetter.length() == state.secondLetter.length()) {
          AddResult(state);
        }
        recursiveSearch(state);
      }
      Truncate(state.firstLetter, this->wordPairs[i].first.length());
      Truncate(state.secondLetter, this->wordPairs[i].second.length());
      state.used[i] = false;
    }
  }
}

void AddResult(LetterAssembler::AssemblerState &state) {
  const auto &result = state.firstLetter;
  if (state.best.length() == 0 || result.length() < state.best.length() ||
      (result.length() == state.best.length() && result < state.best)) {
    state.best = result;
  }
}

void Truncate(std::string &strToTruncate, size_t amount) {
  strToTruncate.resize(strToTruncate.length() - amount);
}
<commit_msg>Remove warning<commit_after>#include "LetterAssembler.hpp"

#include <algorithm>
#include <set>
#include <tuple>

bool LetterAssembler::read(std::istream &inputStream) {
  auto pairCount = 0u;
  auto sumFirstWordLength = 0ull;
  auto sumSecondWordLength = 0ull;
  this->wordPairs.clear();

  inputStream >> pairCount;

  if (pairCount == 0) {
    return false;
  }

  this->wordPairs.reserve(pairCount);

  for (size_t pos = 0; pos < pairCount; ++pos) {
    std::string firstWord;
    std::string secondWord;

    inputStream >> firstWord >> secondWord;

    sumFirstWordLength += firstWord.length();
    sumSecondWordLength += secondWord.length();

    this->wordPairs.push_back(std::make_pair(std::move(firstWord), std::move(secondWord)));
  }

  inputStream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  std::sort(this->wordPairs.begin(), wordPairs.end());
  this->maximumPossibleLength = std::min(sumFirstWordLength, sumSecondWordLength);

  return true;
}

std::string LetterAssembler::assemble() {
  AssemblerState state;
  state.firstLetter.reserve(maximumPossibleLength);
  state.secondLetter.reserve(maximumPossibleLength);
  state.used = std::vector<bool>(this->wordPairs.size(), false);
  this->recursiveSearch(state);
  if (state.best.empty()) {
    return "IMPOSSIBLE";
  } else {
    return state.best;
  }
}

void LetterAssembler::recursiveSearch(AssemblerState &state) {
  auto actualPos = std::min(state.firstLetter.length(), state.secondLetter.length());
  for (auto i = 0u; i < this->wordPairs.size(); ++i) {
    if (!state.used[i]) {
      state.used[i] = true;
      const auto &firstWord = this->wordPairs[i].first;
      const auto &secondWord = this->wordPairs[i].second;
      state.firstLetter.append(firstWord);
      state.secondLetter.append(secondWord);
      auto endPos = std::min(state.firstLetter.length(), state.secondLetter.length());
      auto isGoodContinuation =
          std::equal(&state.firstLetter[actualPos], &state.firstLetter[endPos], &state.secondLetter[actualPos]);
      if (isGoodContinuation) {
        if (state.firstLetter.length() == state.secondLetter.length()) {
          AddResult(state);
        }
        recursiveSearch(state);
      }
      Truncate(state.firstLetter, this->wordPairs[i].first.length());
      Truncate(state.secondLetter, this->wordPairs[i].second.length());
      state.used[i] = false;
    }
  }
}

void AddResult(LetterAssembler::AssemblerState &state) {
  const auto &result = state.firstLetter;
  if (state.best.length() == 0 || result.length() < state.best.length() ||
      (result.length() == state.best.length() && result < state.best)) {
    state.best = result;
  }
}

void Truncate(std::string &strToTruncate, size_t amount) {
  strToTruncate.resize(strToTruncate.length() - amount);
}
<|endoftext|>


<commit_before>#include <apriltag/apriltag.h>
#include <apriltag/tag36h11.h>
#include <apriltag/tag36artoolkit.h>
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace cv;
using std::vector;

#define TAG_SIZE 0.5625f

int main(int argc, char** argv) {
    // Display usage
    if (argc < 2) {
        printf("Usage: %s [cameras...]\n", argv[0]);
        return -1;
    }
    // Parse arguments
    vector<VideoCapture> devices;
    vector<int> device_ids;
    vector<Mat> device_camera_matrix;
    vector<Mat> device_dist_coeffs;
    vector<Mat> cam_transforms;
    for (int i = 1; i < argc; i++) {
        int id = atoi(argv[i]);
        VideoCapture device(id);
        if (!device.isOpened()) {
            std::cerr << "Failed to open video capture device " << id << std::endl;
            continue;
        }
        std::ifstream fin;
        fin.open(argv[i]);
        if (fin.fail()) {
            std::cerr << "Failed to open file " << argv[i] << std::endl;
            continue;
        }
        Mat camera_matrix, dist_coeffs, cam_transform;
        std::string line;
        // TODO Error checking
        while (std::getline(fin, line)) {
            std::stringstream line_stream(line);
            std::string key, equals;
            line_stream >> key >> equals;
            if (key == "camera_matrix") {
                vector<double> data;
                for (int i = 0; i < 9; i++) {
                    double v;
                    line_stream >> v;
                    data.push_back(v);
                }
                camera_matrix = Mat(data, true).reshape(1,3);
            }
            else if (key == "dist_coeffs") {
                vector<double> data;
                for (int i = 0; i < 5; i++) {
                    double v;
                    line_stream >> v;
                    data.push_back(v);
                }
                dist_coeffs = Mat(data, true).reshape(1,1);//one row 5 cols
            }
            else if (key == "transform_matrix"){
                vector<double> data;
                for (int i = 0; i < 16; i++){
                  double v;
                  line_stream >> v;
                  data.push_back(v);
                }
                cam_transform = Mat(data, true).reshape(1,4);
            }
            else {
                std::cerr << "Unrecognized key '" << key << "' in file " << argv[i] << std::endl;
            }
        }
        if (camera_matrix.rows != 3 || camera_matrix.cols != 3) {
            std::cerr << "Error reading camera_matrix in file " << argv[i] << std::endl;
            continue;
        }

        if (dist_coeffs.rows != 3 || dist_coeffs.cols != 3) {
            std::cerr << "Error reading dist_coeffs in file " << argv[i] << std::endl;
            continue;
        }

        if (transform_matrix.rows != 4 || dist_coeffs.cols != 4){
            std::cerr << "Error reading transforms in file " << argv[i] << std::endl;
            continue;
        }

        device.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
        device.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
        device.set(CV_CAP_PROP_FPS, 30);
        devices.push_back(device);
        device_ids.push_back(id);
        device_camera_matrix.push_back(camera_matrix);
        device_dist_coeffs.push_back(dist_coeffs);
        cam_transforms.push_back(cam_transform);
    }
    // Initialize detector
    apriltag_family_t* tf = tag36h11_create();
    tf->black_border = 1;
    apriltag_detector_t* td = apriltag_detector_create();
    apriltag_detector_add_family(td, tf);
    td->quad_decimate = 1.0;
    td->quad_sigma = 0.0;
    td->nthreads = 4;
    td->debug = 0;
    td->refine_edges = 1;
    td->refine_decode = 0;
    td->refine_pose = 0;
    int key = 0;
    Mat frame, gray;
    while (key != 27) { // Quit on escape keypress
        for (size_t i = 0; i < devices.size(); i++) {
            if (!devices[i].isOpened()) {
                continue;
            }

            devices[i] >> frame;
            cvtColor(frame, gray, COLOR_BGR2GRAY);
            image_u8_t im = {
                .width = gray.cols,
                .height = gray.rows,
                .stride = gray.cols,
                .buf = gray.data
            };

            zarray_t* detections = apriltag_detector_detect(td, &im);

            vector<Point2f> img_points(4);
            vector<Point3f> obj_points(4);
            Mat rvec(3, 1, CV_64FC1);
            Mat tvec(3, 1, CV_64FC1);
            for (int j = 0; j < zarray_size(detections); j++) {
                // Get the ith detection
                apriltag_detection_t *det;
                zarray_get(detections, j, &det);

                // Draw onto the frame
                line(frame, Point(det->p[0][0], det->p[0][1]),
                         Point(det->p[1][0], det->p[1][1]),
                         Scalar(0, 0xff, 0), 2);
                line(frame, Point(det->p[0][0], det->p[0][1]),
                         Point(det->p[3][0], det->p[3][1]),
                         Scalar(0, 0, 0xff), 2);
                line(frame, Point(det->p[1][0], det->p[1][1]),
                         Point(det->p[2][0], det->p[2][1]),
                         Scalar(0xff, 0, 0), 2);
                line(frame, Point(det->p[2][0], det->p[2][1]),
                         Point(det->p[3][0], det->p[3][1]),
                         Scalar(0xff, 0, 0), 2);

                // Compute transformation using PnP
                img_points[0] = Point2f(det->p[0][0], det->p[0][1]);
                img_points[1] = Point2f(det->p[1][0], det->p[1][1]);
                img_points[2] = Point2f(det->p[2][0], det->p[2][1]);
                img_points[3] = Point2f(det->p[3][0], det->p[3][1]);

                obj_points[0] = Point3f(-TAG_SIZE * 0.5f, -TAG_SIZE * 0.5f, 0.f);
                obj_points[1] = Point3f( TAG_SIZE * 0.5f, -TAG_SIZE * 0.5f, 0.f);
                obj_points[2] = Point3f( TAG_SIZE * 0.5f,  TAG_SIZE * 0.5f, 0.f);
                obj_points[3] = Point3f(-TAG_SIZE * 0.5f,  TAG_SIZE * 0.5f, 0.f);

                solvePnP(obj_points, img_points, device_camera_matrix[i],
                        device_dist_coeffs[i], rvec, tvec);
                printf("%zu :: %d :: % 3.3f % 3.3f % 3.3f  ::  % 3.3f % 3.3f % 3.3f\n",
                        i, det->id,
                        rvec.at<double>(0), rvec.at<double>(1), rvec.at<double>(2),
                        tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2));
            }

            zarray_destroy(detections);

            imshow(std::to_string(i), frame);
        }

        key = waitKey(16);
    }
    }
<commit_msg>displays tag2orig location<commit_after>#include <apriltag/apriltag.h>
#include <apriltag/tag36h11.h>
#include <apriltag/tag36artoolkit.h>
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace cv;
using std::vector;

#define TAG_SIZE 0.5625f

int main(int argc, char** argv) {
    // Display usage
    if (argc < 2) {
        printf("Usage: %s [cameras...]\n", argv[0]);
        return -1;
    }
    // Parse arguments
    vector<VideoCapture> devices;
    vector<int> device_ids;
    vector<Mat> device_camera_matrix;
    vector<Mat> device_dist_coeffs;
    vector<Mat> cam_transforms;
    for (int i = 1; i < argc; i++) {
        int id = atoi(argv[i]);
        VideoCapture device(id);
        if (!device.isOpened()) {
            std::cerr << "Failed to open video capture device " << id << std::endl;
            continue;
        }
        std::ifstream fin;
        fin.open(argv[i]);
        if (fin.fail()) {
            std::cerr << "Failed to open file " << argv[i] << std::endl;
            continue;
        }
        Mat camera_matrix, dist_coeffs, cam_transform;
        std::string line;
        // TODO Error checking
        while (std::getline(fin, line)) {
            std::stringstream line_stream(line);
            std::string key, equals;
            line_stream >> key >> equals;
            if (key == "camera_matrix") {
                vector<double> data;
                for (int i = 0; i < 9; i++) {
                    double v;
                    line_stream >> v;
                    data.push_back(v);
                }
                camera_matrix = Mat(data, true).reshape(1,3);
            }
            else if (key == "dist_coeffs") {
                vector<double> data;
                for (int i = 0; i < 5; i++) {
                    double v;
                    line_stream >> v;
                    data.push_back(v);
                }
                dist_coeffs = Mat(data, true).reshape(1,1);//one row 5 cols
            }
            else if (key == "transform_matrix"){
                vector<double> data;
                for (int i = 0; i < 16; i++){
                  double v;
                  line_stream >> v;
                  data.push_back(v);
                }
                cam_transform = Mat(data, true).reshape(1,4);
            }
            else {
                std::cerr << "Unrecognized key '" << key << "' in file " << argv[i] << std::endl;
            }
        }
        if (camera_matrix.rows != 3 || camera_matrix.cols != 3) {
            std::cerr << "Error reading camera_matrix in file " << argv[i] << std::endl;
            continue;
        }

        if (dist_coeffs.rows != 3 || dist_coeffs.cols != 3) {
            std::cerr << "Error reading dist_coeffs in file " << argv[i] << std::endl;
            continue;
        }

        if (transform_matrix.rows != 4 || dist_coeffs.cols != 4){
            std::cerr << "Error reading transforms in file " << argv[i] << std::endl;
            continue;
        }

        device.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
        device.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
        device.set(CV_CAP_PROP_FPS, 30);
        devices.push_back(device);
        device_ids.push_back(id);
        device_camera_matrix.push_back(camera_matrix);
        device_dist_coeffs.push_back(dist_coeffs);
        cam_transforms.push_back(cam_transform);
    }
    // Initialize detector
    apriltag_family_t* tf = tag36h11_create();
    tf->black_border = 1;
    apriltag_detector_t* td = apriltag_detector_create();
    apriltag_detector_add_family(td, tf);
    td->quad_decimate = 1.0;
    td->quad_sigma = 0.0;
    td->nthreads = 4;
    td->debug = 0;
    td->refine_edges = 1;
    td->refine_decode = 0;
    td->refine_pose = 0;
    int key = 0;
    Mat frame, gray;
    while (key != 27) { // Quit on escape keypress
        for (size_t i = 0; i < devices.size(); i++) {
            if (!devices[i].isOpened()) {
                continue;
            }

            devices[i] >> frame;
            cvtColor(frame, gray, COLOR_BGR2GRAY);
            image_u8_t im = {
                .width = gray.cols,
                .height = gray.rows,
                .stride = gray.cols,
                .buf = gray.data
            };

            zarray_t* detections = apriltag_detector_detect(td, &im);

            vector<Point2f> img_points(4);
            vector<Point3f> obj_points(4);
            Mat rvec(3, 1, CV_64FC1);
            Mat tvec(3, 1, CV_64FC1);
            for (int j = 0; j < zarray_size(detections); j++) {
                // Get the ith detection
                apriltag_detection_t *det;
                zarray_get(detections, j, &det);

                // Draw onto the frame
                line(frame, Point(det->p[0][0], det->p[0][1]),
                         Point(det->p[1][0], det->p[1][1]),
                         Scalar(0, 0xff, 0), 2);
                line(frame, Point(det->p[0][0], det->p[0][1]),
                         Point(det->p[3][0], det->p[3][1]),
                         Scalar(0, 0, 0xff), 2);
                line(frame, Point(det->p[1][0], det->p[1][1]),
                         Point(det->p[2][0], det->p[2][1]),
                         Scalar(0xff, 0, 0), 2);
                line(frame, Point(det->p[2][0], det->p[2][1]),
                         Point(det->p[3][0], det->p[3][1]),
                         Scalar(0xff, 0, 0), 2);

                // Compute transformation using PnP
                img_points[0] = Point2f(det->p[0][0], det->p[0][1]);
                img_points[1] = Point2f(det->p[1][0], det->p[1][1]);
                img_points[2] = Point2f(det->p[2][0], det->p[2][1]);
                img_points[3] = Point2f(det->p[3][0], det->p[3][1]);

                obj_points[0] = Point3f(-TAG_SIZE * 0.5f, -TAG_SIZE * 0.5f, 0.f);
                obj_points[1] = Point3f( TAG_SIZE * 0.5f, -TAG_SIZE * 0.5f, 0.f);
                obj_points[2] = Point3f( TAG_SIZE * 0.5f,  TAG_SIZE * 0.5f, 0.f);
                obj_points[3] = Point3f(-TAG_SIZE * 0.5f,  TAG_SIZE * 0.5f, 0.f);

                solvePnP(obj_points, img_points, device_camera_matrix[i],
                        device_dist_coeffs[i], rvec, tvec);
                Matx33d r;
                Rodrigues(rvec,r);

                vector<double> data;
                data.push_back(r(0,0));
                data.push_back(r(0,1));
                data.push_back(r(0,2));
                data.push_back(tvec.at<double>(0));
                data.push_back(r(1,0));
                data.push_back(r(1,1));
                data.push_back(r(1,2));
                data.push_back(tvec.at<double>(0));
                data.push_back(r(2,0));
                data.push_back(r(2,1));
                data.push_back(r(2,2));
                data.push_back(tvec.at<double>(0));
                data.push_back(0);
                data.push_back(0);
                data.push_back(0);
                data.push_back(1);
                Mat tag2cam = Mat(data,true).reshape(1,4);

                vector<double> data2;
                data2.push_back(0);
                data2.push_back(0);
                data2.push_back(0);
                data2.push_back(1);
                Mat genout = Mat(data2,true).reshape(1,1);

                Mat tag2orig = tag2cam * cam_transforms[i];
                Mat tagXYZS = tag2orig * genout;
                printf("%zu :: %d :: % 3.3f % 3.3f % 3.3f",
                        i, det->id,
                        tagXYZS.at<double>(0,0), tagXYZS.at<double>(1,0), tagXYZS.at<double>(2,0));
            }

            zarray_destroy(detections);

            imshow(std::to_string(i), frame);
        }

        key = waitKey(16);
    }
    }
<|endoftext|>


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

#if defined(_MSC_VER)
#pragma warning(disable: 4718)
#endif

#include "compiler/translator/Types.h"

#include <climits>

TType::TType(const TPublicType &p)
    : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier),
      primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize),
      interfaceBlock(0), structure(0)
{
    if (p.userDef)
    {
        structure = p.userDef->getStruct();
    }
}

bool TType::equals(const TType &other) const
{
    if (type != other.type || precision != other.precision ||
        primarySize != other.primarySize || secondarySize != other.secondarySize ||
        array != other.array || (array && arraySize != other.arraySize) ||
        interfaceBlock != other.interfaceBlock || structure != other.structure)
    {
        return false;
    }
    if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock)))
    {
        return false;
    }
    if (structure && !structure->equals(*(other.structure)))
    {
        return false;
    }
    return true;
}

bool TField::equals(const TField &other) const
{
    ASSERT(mType && mName);
    ASSERT(other.mType && other.mName);
    return mType->equals(*(other.mType)) && *mName == *(other.mName);
}

bool TFieldListCollection::equals(const TFieldListCollection &other) const
{
    ASSERT(mName && mFields);
    ASSERT(other.mName && other.mFields);
    if (*mName != *(other.mName))
         return false;
    if (mFields->size() != other.mFields->size())
        return false;
    for (size_t ii = 0; ii < mFields->size(); ++ii)
    {
        ASSERT((*mFields)[ii] && (*(other.mFields))[ii]);
        if (!(*mFields)[ii]->equals(*((*(other.mFields))[ii])))
            return false;
    }
    return true;
}

bool TInterfaceBlock::equals(const TInterfaceBlock &other) const
{
    if (!TFieldListCollection::equals(other))
        return false;
    // TODO(zmo): do we need to consider mBlockStorage and mMatrixPacking?
    return mArraySize == other.mArraySize;
}

//
// Recursively generate mangled names.
//
TString TType::buildMangledName() const
{
    TString mangledName;
    if (isMatrix())
        mangledName += 'm';
    else if (isVector())
        mangledName += 'v';

    switch (type)
    {
      case EbtFloat:                mangledName += 'f';      break;
      case EbtInt:                  mangledName += 'i';      break;
      case EbtUInt:                 mangledName += 'u';      break;
      case EbtBool:                 mangledName += 'b';      break;
      case EbtSampler2D:            mangledName += "s2";     break;
      case EbtSampler3D:            mangledName += "s3";     break;
      case EbtSamplerCube:          mangledName += "sC";     break;
      case EbtSampler2DArray:       mangledName += "s2a";    break;
      case EbtSamplerExternalOES:   mangledName += "sext";   break;
      case EbtSampler2DRect:        mangledName += "s2r";    break;
      case EbtISampler2D:           mangledName += "is2";    break;
      case EbtISampler3D:           mangledName += "is3";    break;
      case EbtISamplerCube:         mangledName += "isC";    break;
      case EbtISampler2DArray:      mangledName += "is2a";   break;
      case EbtUSampler2D:           mangledName += "us2";    break;
      case EbtUSampler3D:           mangledName += "us3";    break;
      case EbtUSamplerCube:         mangledName += "usC";    break;
      case EbtUSampler2DArray:      mangledName += "us2a";   break;
      case EbtSampler2DShadow:      mangledName += "s2s";    break;
      case EbtSamplerCubeShadow:    mangledName += "sCs";    break;
      case EbtSampler2DArrayShadow: mangledName += "s2as";   break;
      case EbtStruct:               mangledName += structure->mangledName(); break;
      case EbtInterfaceBlock:       mangledName += interfaceBlock->mangledName(); break;
      default:                      UNREACHABLE();
    }

    if (isMatrix())
    {
        mangledName += static_cast<char>('0' + getCols());
        mangledName += static_cast<char>('x');
        mangledName += static_cast<char>('0' + getRows());
    }
    else
    {
        mangledName += static_cast<char>('0' + getNominalSize());
    }

    if (isArray())
    {
        char buf[20];
        snprintf(buf, sizeof(buf), "%d", arraySize);
        mangledName += '[';
        mangledName += buf;
        mangledName += ']';
    }
    return mangledName;
}

size_t TType::getObjectSize() const
{
    size_t totalSize;

    if (getBasicType() == EbtStruct)
        totalSize = structure->objectSize();
    else
        totalSize = primarySize * secondarySize;

    if (isArray())
    {
        size_t arraySize = getArraySize();
        if (arraySize > INT_MAX / totalSize)
            totalSize = INT_MAX;
        else
            totalSize *= arraySize;
    }

    return totalSize;
}

bool TStructure::containsArrays() const
{
    for (size_t i = 0; i < mFields->size(); ++i) {
        const TType* fieldType = (*mFields)[i]->type();
        if (fieldType->isArray() || fieldType->isStructureContainingArrays())
            return true;
    }
    return false;
}

TString TFieldListCollection::buildMangledName() const
{
    TString mangledName(mangledNamePrefix());
    mangledName += *mName;
    for (size_t i = 0; i < mFields->size(); ++i)
    {
        mangledName += '-';
        mangledName += (*mFields)[i]->type()->getMangledName();
    }
    return mangledName;
}

size_t TFieldListCollection::calculateObjectSize() const
{
    size_t size = 0;
    for (size_t i = 0; i < mFields->size(); ++i) {
        size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
        if (fieldSize > INT_MAX - size)
            size = INT_MAX;
        else
            size += fieldSize;
    }
    return size;
}

int TStructure::calculateDeepestNesting() const
{
    int maxNesting = 0;
    for (size_t i = 0; i < mFields->size(); ++i) {
        maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
    }
    return 1 + maxNesting;
}
<commit_msg>Fix missing <algorithm> include.<commit_after>//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#if defined(_MSC_VER)
#pragma warning(disable: 4718)
#endif

#include "compiler/translator/Types.h"

#include <algorithm>
#include <climits>

TType::TType(const TPublicType &p)
    : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier),
      primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize),
      interfaceBlock(0), structure(0)
{
    if (p.userDef)
    {
        structure = p.userDef->getStruct();
    }
}

bool TType::equals(const TType &other) const
{
    if (type != other.type || precision != other.precision ||
        primarySize != other.primarySize || secondarySize != other.secondarySize ||
        array != other.array || (array && arraySize != other.arraySize) ||
        interfaceBlock != other.interfaceBlock || structure != other.structure)
    {
        return false;
    }
    if (interfaceBlock && !interfaceBlock->equals(*(other.interfaceBlock)))
    {
        return false;
    }
    if (structure && !structure->equals(*(other.structure)))
    {
        return false;
    }
    return true;
}

bool TField::equals(const TField &other) const
{
    ASSERT(mType && mName);
    ASSERT(other.mType && other.mName);
    return mType->equals(*(other.mType)) && *mName == *(other.mName);
}

bool TFieldListCollection::equals(const TFieldListCollection &other) const
{
    ASSERT(mName && mFields);
    ASSERT(other.mName && other.mFields);
    if (*mName != *(other.mName))
         return false;
    if (mFields->size() != other.mFields->size())
        return false;
    for (size_t ii = 0; ii < mFields->size(); ++ii)
    {
        ASSERT((*mFields)[ii] && (*(other.mFields))[ii]);
        if (!(*mFields)[ii]->equals(*((*(other.mFields))[ii])))
            return false;
    }
    return true;
}

bool TInterfaceBlock::equals(const TInterfaceBlock &other) const
{
    if (!TFieldListCollection::equals(other))
        return false;
    // TODO(zmo): do we need to consider mBlockStorage and mMatrixPacking?
    return mArraySize == other.mArraySize;
}

//
// Recursively generate mangled names.
//
TString TType::buildMangledName() const
{
    TString mangledName;
    if (isMatrix())
        mangledName += 'm';
    else if (isVector())
        mangledName += 'v';

    switch (type)
    {
      case EbtFloat:                mangledName += 'f';      break;
      case EbtInt:                  mangledName += 'i';      break;
      case EbtUInt:                 mangledName += 'u';      break;
      case EbtBool:                 mangledName += 'b';      break;
      case EbtSampler2D:            mangledName += "s2";     break;
      case EbtSampler3D:            mangledName += "s3";     break;
      case EbtSamplerCube:          mangledName += "sC";     break;
      case EbtSampler2DArray:       mangledName += "s2a";    break;
      case EbtSamplerExternalOES:   mangledName += "sext";   break;
      case EbtSampler2DRect:        mangledName += "s2r";    break;
      case EbtISampler2D:           mangledName += "is2";    break;
      case EbtISampler3D:           mangledName += "is3";    break;
      case EbtISamplerCube:         mangledName += "isC";    break;
      case EbtISampler2DArray:      mangledName += "is2a";   break;
      case EbtUSampler2D:           mangledName += "us2";    break;
      case EbtUSampler3D:           mangledName += "us3";    break;
      case EbtUSamplerCube:         mangledName += "usC";    break;
      case EbtUSampler2DArray:      mangledName += "us2a";   break;
      case EbtSampler2DShadow:      mangledName += "s2s";    break;
      case EbtSamplerCubeShadow:    mangledName += "sCs";    break;
      case EbtSampler2DArrayShadow: mangledName += "s2as";   break;
      case EbtStruct:               mangledName += structure->mangledName(); break;
      case EbtInterfaceBlock:       mangledName += interfaceBlock->mangledName(); break;
      default:                      UNREACHABLE();
    }

    if (isMatrix())
    {
        mangledName += static_cast<char>('0' + getCols());
        mangledName += static_cast<char>('x');
        mangledName += static_cast<char>('0' + getRows());
    }
    else
    {
        mangledName += static_cast<char>('0' + getNominalSize());
    }

    if (isArray())
    {
        char buf[20];
        snprintf(buf, sizeof(buf), "%d", arraySize);
        mangledName += '[';
        mangledName += buf;
        mangledName += ']';
    }
    return mangledName;
}

size_t TType::getObjectSize() const
{
    size_t totalSize;

    if (getBasicType() == EbtStruct)
        totalSize = structure->objectSize();
    else
        totalSize = primarySize * secondarySize;

    if (isArray())
    {
        size_t arraySize = getArraySize();
        if (arraySize > INT_MAX / totalSize)
            totalSize = INT_MAX;
        else
            totalSize *= arraySize;
    }

    return totalSize;
}

bool TStructure::containsArrays() const
{
    for (size_t i = 0; i < mFields->size(); ++i) {
        const TType* fieldType = (*mFields)[i]->type();
        if (fieldType->isArray() || fieldType->isStructureContainingArrays())
            return true;
    }
    return false;
}

TString TFieldListCollection::buildMangledName() const
{
    TString mangledName(mangledNamePrefix());
    mangledName += *mName;
    for (size_t i = 0; i < mFields->size(); ++i)
    {
        mangledName += '-';
        mangledName += (*mFields)[i]->type()->getMangledName();
    }
    return mangledName;
}

size_t TFieldListCollection::calculateObjectSize() const
{
    size_t size = 0;
    for (size_t i = 0; i < mFields->size(); ++i) {
        size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
        if (fieldSize > INT_MAX - size)
            size = INT_MAX;
        else
            size += fieldSize;
    }
    return size;
}

int TStructure::calculateDeepestNesting() const
{
    int maxNesting = 0;
    for (size_t i = 0; i < mFields->size(); ++i) {
        maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
    }
    return 1 + maxNesting;
}
<|endoftext|>


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

#include "jni_compiler.h"

#include "class_linker.h"
#include "compilation_unit.h"
#include "compiled_method.h"
#include "compiler.h"
#include "compiler_llvm.h"
#include "ir_builder.h"
#include "logging.h"
#include "oat_compilation_unit.h"
#include "object.h"
#include "runtime.h"
#include "runtime_support_func.h"
#include "shadow_frame.h"
#include "utils_llvm.h"

#include <llvm/Analysis/Verifier.h>
#include <llvm/BasicBlock.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Type.h>

namespace art {
namespace compiler_llvm {

using namespace runtime_support;

JniCompiler::JniCompiler(CompilationUnit* cunit,
                         Compiler const& compiler,
                         OatCompilationUnit* oat_compilation_unit)
: cunit_(cunit), compiler_(&compiler), module_(cunit_->GetModule()),
  context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
  oat_compilation_unit_(oat_compilation_unit),
  access_flags_(oat_compilation_unit->access_flags_),
  method_idx_(oat_compilation_unit->method_idx_),
  class_linker_(oat_compilation_unit->class_linker_),
  class_loader_(oat_compilation_unit->class_loader_),
  dex_cache_(oat_compilation_unit->dex_cache_),
  dex_file_(oat_compilation_unit->dex_file_),
  method_(dex_cache_->GetResolvedMethod(method_idx_)),
  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {

  // Check: Ensure that the method is resolved
  CHECK_NE(method_, static_cast<art::Method*>(NULL));

  // Check: Ensure that JNI compiler will only get "native" method
  CHECK((access_flags_ & kAccNative) != 0);
}

CompiledMethod* JniCompiler::Compile() {
  const bool is_static = (access_flags_ & kAccStatic) != 0;
  const bool is_synchronized = (access_flags_ & kAccSynchronized) != 0;
  DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx_);
  char const return_shorty = dex_file_->GetMethodShorty(method_id)[0];
  llvm::Value* this_object_or_class_object;

  CreateFunction();

  // Set argument name
  llvm::Function::arg_iterator arg_begin(func_->arg_begin());
  llvm::Function::arg_iterator arg_end(func_->arg_end());
  llvm::Function::arg_iterator arg_iter(arg_begin);

  DCHECK_NE(arg_iter, arg_end);
  arg_iter->setName("method");
  llvm::Value* method_object_addr = arg_iter++;

  if (!is_static) {
    // Non-static, the second argument is "this object"
    this_object_or_class_object = arg_iter++;
  } else {
    // Load class object
    this_object_or_class_object =
        irb_.LoadFromObjectOffset(method_object_addr,
                                  Method::DeclaringClassOffset().Int32Value(),
                                  irb_.getJObjectTy());
  }
  // Actual argument (ignore method and this object)
  arg_begin = arg_iter;

  // Count the number of Object* arguments
  uint32_t sirt_size = 1;
  // "this" object pointer for non-static
  // "class" object pointer for static
  for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
    arg_iter->setName(StringPrintf("a%u", i));
    if (arg_iter->getType() == irb_.getJObjectTy()) {
      ++sirt_size;
    }
  }

  // Get thread object
  llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));

  // Shadow stack
  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
  llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);

  // Zero-initialization of the shadow frame
  llvm::ConstantAggregateZero* zero_initializer =
    llvm::ConstantAggregateZero::get(shadow_frame_type);
  irb_.CreateStore(zero_initializer, shadow_frame_);

  // Store the method pointer
  llvm::Value* method_field_addr =
    irb_.CreatePtrDisp(shadow_frame_,
                       irb_.getPtrEquivInt(ShadowFrame::MethodOffset()),
                       irb_.getJObjectTy()->getPointerTo());
  irb_.CreateStore(method_object_addr, method_field_addr);

  // Store the line number
  irb_.StoreToObjectOffset(shadow_frame_,
                           ShadowFrame::LineNumOffset(),
                           irb_.getInt32(dex_file_->GetLineNumFromPC(method_, 0)));

  // Store the number of the pointer slots
  irb_.StoreToObjectOffset(shadow_frame_,
                           ShadowFrame::NumberOfReferencesOffset(),
                           irb_.getInt32(sirt_size));

  // Push the shadow frame
  llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
  irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);

  // Get JNIEnv
  llvm::Value* jni_env_object_addr =
      irb_.LoadFromObjectOffset(thread_object_addr,
                                Thread::JniEnvOffset().Int32Value(),
                                irb_.getJObjectTy());

  // Set thread state to kNative
  irb_.StoreToObjectOffset(thread_object_addr,
                           Thread::StateOffset().Int32Value(),
                           irb_.getInt32(kNative));

  // Get callee code_addr
  llvm::Value* code_addr =
      irb_.LoadFromObjectOffset(method_object_addr,
                                Method::NativeMethodOffset().Int32Value(),
                                GetFunctionType(method_idx_, is_static, true)->getPointerTo());

  // Load actual parameters
  std::vector<llvm::Value*> args;

  // The 1st parameter: JNIEnv*
  args.push_back(jni_env_object_addr);

  // Variables for GetElementPtr
  llvm::Value* gep_index[] = {
    irb_.getInt32(0), // No displacement for shadow frame pointer
    irb_.getInt32(1), // SIRT
    NULL,
  };

  size_t sirt_member_index = 0;

  // Store the "this object or class object" to SIRT
  gep_index[2] = irb_.getInt32(sirt_member_index++);
  llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
  irb_.CreateStore(this_object_or_class_object, sirt_field_addr);
  // Push the "this object or class object" to out args
  args.push_back(irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
  // Store arguments to SIRT, and push back to args
  for (arg_iter = arg_begin; arg_iter != arg_end; ++arg_iter) {
    if (arg_iter->getType() == irb_.getJObjectTy()) {
      // Store the reference type arguments to SIRT
      gep_index[2] = irb_.getInt32(sirt_member_index++);
      llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
      irb_.CreateStore(arg_iter, sirt_field_addr);
      // Note null is placed in the SIRT but the jobject passed to the native code must be null
      // (not a pointer into the SIRT as with regular references).
      llvm::Value* equal_null = irb_.CreateICmpEQ(arg_iter, irb_.getJNull());
      llvm::Value* arg =
          irb_.CreateSelect(equal_null,
                            irb_.getJNull(),
                            irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
      args.push_back(arg);
    } else {
      args.push_back(arg_iter);
    }
  }

  // Acquire lock for synchronized methods.
  if (is_synchronized) {
    // Acquire lock
    irb_.CreateCall(irb_.GetRuntime(LockObject), this_object_or_class_object);

    // Check exception pending
    llvm::Value* exception_pending = irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));

    // Create two basic block for branch
    llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "B.cont", func_);
    llvm::BasicBlock* block_exception_ = llvm::BasicBlock::Create(*context_, "B.exception", func_);

    // Branch by exception_pending
    irb_.CreateCondBr(exception_pending, block_exception_, block_cont);

    // If exception pending
    irb_.SetInsertPoint(block_exception_);
    // TODO: Set thread state?
    // Pop the shadow frame
    irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
    // Unwind
    if (return_shorty != 'V') {
      irb_.CreateRet(irb_.getJZero(return_shorty));
    } else {
      irb_.CreateRetVoid();
    }

    // If no exception pending
    irb_.SetInsertPoint(block_cont);
  }

  // saved_local_ref_cookie = env->local_ref_cookie
  llvm::Value* saved_local_ref_cookie =
      irb_.LoadFromObjectOffset(jni_env_object_addr,
                                JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                                irb_.getInt32Ty());

  // env->local_ref_cookie = env->locals.segment_state
  llvm::Value* segment_state =
      irb_.LoadFromObjectOffset(jni_env_object_addr,
                                JNIEnvExt::SegmentStateOffset().Int32Value(),
                                irb_.getInt32Ty());
  irb_.StoreToObjectOffset(jni_env_object_addr,
                           JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                           segment_state);

  // Call!!!
  llvm::Value* retval = irb_.CreateCall(code_addr, args);

  // Release lock for synchronized methods.
  if (is_synchronized) {
    irb_.CreateCall(irb_.GetRuntime(UnlockObject), this_object_or_class_object);
  }

  // Set thread state to kRunnable
  irb_.StoreToObjectOffset(thread_object_addr,
                           Thread::StateOffset().Int32Value(),
                           irb_.getInt32(kRunnable));

  if (return_shorty == 'L') {
    // If the return value is reference, it may point to SIRT, we should decode it.
    retval = irb_.CreateCall2(irb_.GetRuntime(DecodeJObjectInThread),
                              thread_object_addr,
                              retval);
  }

  // env->locals.segment_state = env->local_ref_cookie
  llvm::Value* local_ref_cookie =
      irb_.LoadFromObjectOffset(jni_env_object_addr,
                                JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                                irb_.getInt32Ty());
  irb_.StoreToObjectOffset(jni_env_object_addr,
                           JNIEnvExt::SegmentStateOffset().Int32Value(),
                           local_ref_cookie);

  // env->local_ref_cookie = saved_local_ref_cookie
  irb_.StoreToObjectOffset(jni_env_object_addr,
                           JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                           saved_local_ref_cookie);

  // Pop the shadow frame
  irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));

  // Return!
  if (return_shorty != 'V') {
    irb_.CreateRet(retval);
  } else {
    irb_.CreateRetVoid();
  }

  // Verify the generated bitcode
  llvm::verifyFunction(*func_, llvm::PrintMessageAction);

  CompiledMethod* compiled_method =
      new CompiledMethod(cunit_->GetInstructionSet(),
                         cunit_->GetElfIndex(),
                         elf_func_idx_);

  cunit_->RegisterCompiledMethod(func_, compiled_method);

  return compiled_method;
}

void JniCompiler::CreateFunction() {
  // LLVM function name
  std::string func_name(ElfFuncName(elf_func_idx_));

  // Get function type
  llvm::FunctionType* func_type =
    GetFunctionType(method_idx_, method_->IsStatic(), false);

  // Create function
  func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
                                 func_name, module_);

  // Create basic block
  llvm::BasicBlock* basic_block = llvm::BasicBlock::Create(*context_, "B0", func_);

  // Set insert point
  irb_.SetInsertPoint(basic_block);
}

llvm::FunctionType* JniCompiler::GetFunctionType(uint32_t method_idx,
                                                 bool is_static, bool is_native_function) {
  // Get method signature
  DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);

  uint32_t shorty_size;
  char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
  CHECK_GE(shorty_size, 1u);

  // Get return type
  llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);

  // Get argument type
  std::vector<llvm::Type*> args_type;

  args_type.push_back(irb_.getJObjectTy()); // method object pointer

  if (!is_static || is_native_function) {
    // "this" object pointer for non-static
    // "class" object pointer for static naitve
    args_type.push_back(irb_.getJType('L', kAccurate));
  }

  for (uint32_t i = 1; i < shorty_size; ++i) {
    args_type.push_back(irb_.getJType(shorty[i], kAccurate));
  }

  return llvm::FunctionType::get(ret_type, args_type, false);
}

} // namespace compiler_llvm
} // namespace art
<commit_msg>am 69eafaae: Fix jni compiler bug (Compiler_llvm).<commit_after>/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "jni_compiler.h"

#include "class_linker.h"
#include "compilation_unit.h"
#include "compiled_method.h"
#include "compiler.h"
#include "compiler_llvm.h"
#include "ir_builder.h"
#include "logging.h"
#include "oat_compilation_unit.h"
#include "object.h"
#include "runtime.h"
#include "runtime_support_func.h"
#include "shadow_frame.h"
#include "utils_llvm.h"

#include <llvm/Analysis/Verifier.h>
#include <llvm/BasicBlock.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Type.h>

namespace art {
namespace compiler_llvm {

using namespace runtime_support;

JniCompiler::JniCompiler(CompilationUnit* cunit,
                         Compiler const& compiler,
                         OatCompilationUnit* oat_compilation_unit)
: cunit_(cunit), compiler_(&compiler), module_(cunit_->GetModule()),
  context_(cunit_->GetLLVMContext()), irb_(*cunit_->GetIRBuilder()),
  oat_compilation_unit_(oat_compilation_unit),
  access_flags_(oat_compilation_unit->access_flags_),
  method_idx_(oat_compilation_unit->method_idx_),
  class_linker_(oat_compilation_unit->class_linker_),
  class_loader_(oat_compilation_unit->class_loader_),
  dex_cache_(oat_compilation_unit->dex_cache_),
  dex_file_(oat_compilation_unit->dex_file_),
  method_(dex_cache_->GetResolvedMethod(method_idx_)),
  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {

  // Check: Ensure that the method is resolved
  CHECK_NE(method_, static_cast<art::Method*>(NULL));

  // Check: Ensure that JNI compiler will only get "native" method
  CHECK((access_flags_ & kAccNative) != 0);
}

CompiledMethod* JniCompiler::Compile() {
  const bool is_static = (access_flags_ & kAccStatic) != 0;
  const bool is_synchronized = (access_flags_ & kAccSynchronized) != 0;
  DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx_);
  char const return_shorty = dex_file_->GetMethodShorty(method_id)[0];
  llvm::Value* this_object_or_class_object;

  CreateFunction();

  // Set argument name
  llvm::Function::arg_iterator arg_begin(func_->arg_begin());
  llvm::Function::arg_iterator arg_end(func_->arg_end());
  llvm::Function::arg_iterator arg_iter(arg_begin);

  DCHECK_NE(arg_iter, arg_end);
  arg_iter->setName("method");
  llvm::Value* method_object_addr = arg_iter++;

  if (!is_static) {
    // Non-static, the second argument is "this object"
    this_object_or_class_object = arg_iter++;
  } else {
    // Load class object
    this_object_or_class_object =
        irb_.LoadFromObjectOffset(method_object_addr,
                                  Method::DeclaringClassOffset().Int32Value(),
                                  irb_.getJObjectTy());
  }
  // Actual argument (ignore method and this object)
  arg_begin = arg_iter;

  // Count the number of Object* arguments
  uint32_t sirt_size = 1;
  // "this" object pointer for non-static
  // "class" object pointer for static
  for (unsigned i = 0; arg_iter != arg_end; ++i, ++arg_iter) {
    arg_iter->setName(StringPrintf("a%u", i));
    if (arg_iter->getType() == irb_.getJObjectTy()) {
      ++sirt_size;
    }
  }

  // Get thread object
  llvm::Value* thread_object_addr = irb_.CreateCall(irb_.GetRuntime(GetCurrentThread));

  // Shadow stack
  llvm::StructType* shadow_frame_type = irb_.getShadowFrameTy(sirt_size);
  llvm::AllocaInst* shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);

  // Zero-initialization of the shadow frame
  llvm::ConstantAggregateZero* zero_initializer =
    llvm::ConstantAggregateZero::get(shadow_frame_type);
  irb_.CreateStore(zero_initializer, shadow_frame_);

  // Store the method pointer
  llvm::Value* method_field_addr =
    irb_.CreatePtrDisp(shadow_frame_,
                       irb_.getPtrEquivInt(ShadowFrame::MethodOffset()),
                       irb_.getJObjectTy()->getPointerTo());
  irb_.CreateStore(method_object_addr, method_field_addr);

  // Store the line number
  irb_.StoreToObjectOffset(shadow_frame_,
                           ShadowFrame::LineNumOffset(),
                           irb_.getInt32(dex_file_->GetLineNumFromPC(method_, 0)));

  // Store the number of the pointer slots
  irb_.StoreToObjectOffset(shadow_frame_,
                           ShadowFrame::NumberOfReferencesOffset(),
                           irb_.getInt32(sirt_size));

  // Push the shadow frame
  llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
  irb_.CreateCall(irb_.GetRuntime(PushShadowFrame), shadow_frame_upcast);

  // Get JNIEnv
  llvm::Value* jni_env_object_addr =
      irb_.LoadFromObjectOffset(thread_object_addr,
                                Thread::JniEnvOffset().Int32Value(),
                                irb_.getJObjectTy());

  // Set thread state to kNative
  irb_.StoreToObjectOffset(thread_object_addr,
                           Thread::StateOffset().Int32Value(),
                           irb_.getInt32(kNative));

  // Get callee code_addr
  llvm::Value* code_addr =
      irb_.LoadFromObjectOffset(method_object_addr,
                                Method::NativeMethodOffset().Int32Value(),
                                GetFunctionType(method_idx_, is_static, true)->getPointerTo());

  // Load actual parameters
  std::vector<llvm::Value*> args;

  // The 1st parameter: JNIEnv*
  args.push_back(jni_env_object_addr);

  // Variables for GetElementPtr
  llvm::Value* gep_index[] = {
    irb_.getInt32(0), // No displacement for shadow frame pointer
    irb_.getInt32(1), // SIRT
    NULL,
  };

  size_t sirt_member_index = 0;

  // Store the "this object or class object" to SIRT
  gep_index[2] = irb_.getInt32(sirt_member_index++);
  llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
  irb_.CreateStore(this_object_or_class_object, sirt_field_addr);
  // Push the "this object or class object" to out args
  args.push_back(irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
  // Store arguments to SIRT, and push back to args
  for (arg_iter = arg_begin; arg_iter != arg_end; ++arg_iter) {
    if (arg_iter->getType() == irb_.getJObjectTy()) {
      // Store the reference type arguments to SIRT
      gep_index[2] = irb_.getInt32(sirt_member_index++);
      llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
      irb_.CreateStore(arg_iter, sirt_field_addr);
      // Note null is placed in the SIRT but the jobject passed to the native code must be null
      // (not a pointer into the SIRT as with regular references).
      llvm::Value* equal_null = irb_.CreateICmpEQ(arg_iter, irb_.getJNull());
      llvm::Value* arg =
          irb_.CreateSelect(equal_null,
                            irb_.getJNull(),
                            irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
      args.push_back(arg);
    } else {
      args.push_back(arg_iter);
    }
  }

  // Acquire lock for synchronized methods.
  if (is_synchronized) {
    // Acquire lock
    irb_.CreateCall(irb_.GetRuntime(LockObject), this_object_or_class_object);

    // Check exception pending
    llvm::Value* exception_pending = irb_.CreateCall(irb_.GetRuntime(IsExceptionPending));

    // Create two basic block for branch
    llvm::BasicBlock* block_cont = llvm::BasicBlock::Create(*context_, "B.cont", func_);
    llvm::BasicBlock* block_exception_ = llvm::BasicBlock::Create(*context_, "B.exception", func_);

    // Branch by exception_pending
    irb_.CreateCondBr(exception_pending, block_exception_, block_cont);

    // If exception pending
    irb_.SetInsertPoint(block_exception_);
    // TODO: Set thread state?
    // Pop the shadow frame
    irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
    // Unwind
    if (return_shorty != 'V') {
      irb_.CreateRet(irb_.getJZero(return_shorty));
    } else {
      irb_.CreateRetVoid();
    }

    // If no exception pending
    irb_.SetInsertPoint(block_cont);
  }

  // saved_local_ref_cookie = env->local_ref_cookie
  llvm::Value* saved_local_ref_cookie =
      irb_.LoadFromObjectOffset(jni_env_object_addr,
                                JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                                irb_.getInt32Ty());

  // env->local_ref_cookie = env->locals.segment_state
  llvm::Value* segment_state =
      irb_.LoadFromObjectOffset(jni_env_object_addr,
                                JNIEnvExt::SegmentStateOffset().Int32Value(),
                                irb_.getInt32Ty());
  irb_.StoreToObjectOffset(jni_env_object_addr,
                           JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                           segment_state);

  // Call!!!
  llvm::Value* retval = irb_.CreateCall(code_addr, args);

  // Release lock for synchronized methods.
  if (is_synchronized) {
    irb_.CreateCall(irb_.GetRuntime(UnlockObject), this_object_or_class_object);
  }

  // Set thread state to kRunnable
  irb_.StoreToObjectOffset(thread_object_addr,
                           Thread::StateOffset().Int32Value(),
                           irb_.getInt32(kRunnable));

  // Do a suspend check
  irb_.CreateCall(irb_.GetRuntime(TestSuspend));

  if (return_shorty == 'L') {
    // If the return value is reference, it may point to SIRT, we should decode it.
    retval = irb_.CreateCall2(irb_.GetRuntime(DecodeJObjectInThread),
                              thread_object_addr,
                              retval);
  }

  // env->locals.segment_state = env->local_ref_cookie
  llvm::Value* local_ref_cookie =
      irb_.LoadFromObjectOffset(jni_env_object_addr,
                                JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                                irb_.getInt32Ty());
  irb_.StoreToObjectOffset(jni_env_object_addr,
                           JNIEnvExt::SegmentStateOffset().Int32Value(),
                           local_ref_cookie);

  // env->local_ref_cookie = saved_local_ref_cookie
  irb_.StoreToObjectOffset(jni_env_object_addr,
                           JNIEnvExt::LocalRefCookieOffset().Int32Value(),
                           saved_local_ref_cookie);

  // Pop the shadow frame
  irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));

  // Return!
  if (return_shorty != 'V') {
    irb_.CreateRet(retval);
  } else {
    irb_.CreateRetVoid();
  }

  // Verify the generated bitcode
  llvm::verifyFunction(*func_, llvm::PrintMessageAction);

  CompiledMethod* compiled_method =
      new CompiledMethod(cunit_->GetInstructionSet(),
                         cunit_->GetElfIndex(),
                         elf_func_idx_);

  cunit_->RegisterCompiledMethod(func_, compiled_method);

  return compiled_method;
}

void JniCompiler::CreateFunction() {
  // LLVM function name
  std::string func_name(ElfFuncName(elf_func_idx_));

  // Get function type
  llvm::FunctionType* func_type =
    GetFunctionType(method_idx_, method_->IsStatic(), false);

  // Create function
  func_ = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage,
                                 func_name, module_);

  // Create basic block
  llvm::BasicBlock* basic_block = llvm::BasicBlock::Create(*context_, "B0", func_);

  // Set insert point
  irb_.SetInsertPoint(basic_block);
}

llvm::FunctionType* JniCompiler::GetFunctionType(uint32_t method_idx,
                                                 bool is_static, bool is_native_function) {
  // Get method signature
  DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);

  uint32_t shorty_size;
  char const* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
  CHECK_GE(shorty_size, 1u);

  // Get return type
  llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);

  // Get argument type
  std::vector<llvm::Type*> args_type;

  args_type.push_back(irb_.getJObjectTy()); // method object pointer

  if (!is_static || is_native_function) {
    // "this" object pointer for non-static
    // "class" object pointer for static naitve
    args_type.push_back(irb_.getJType('L', kAccurate));
  }

  for (uint32_t i = 1; i < shorty_size; ++i) {
    args_type.push_back(irb_.getJType(shorty[i], kAccurate));
  }

  return llvm::FunctionType::get(ret_type, args_type, false);
}

} // namespace compiler_llvm
} // namespace art
<|endoftext|>


<commit_before>/*****************************************************************************
 * libVLC backend for the Phonon library                                     *
 *                                                                           *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
 *                                                                           *
 * This program is free software; you can redistribute it and/or             *
 * modify it under the terms of the GNU Lesser General Public                *
 * License as published by the Free Software Foundation; either              *
 * version 2.1 of the License, or (at your option) any later version.        *
 *                                                                           *
 * This program is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "devicemanager.h"
#include "devicescan.h"
#include "backend.h"
//#include "videowidget.h"
//#include "widgetrenderer.h"
#include "vlcloader.h"

#ifdef PHONON_PULSESUPPORT
#  include <phonon/pulsesupport.h>
#endif

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace VLC {

/**
 * Constructs a device info object and sets it's device identifiers.
 */
DeviceInfo::DeviceInfo( const QByteArray& name, const QString& description)
{
    // Get an id
    static int counter = 0;
    id = counter++;

    // Get name and description for the device
    this->name = name;
    this->description = description;
    capabilities = None;
}

/**
 * Constructs a device manager and immediately updates the device lists.
 */
DeviceManager::DeviceManager(Backend *parent)
        : QObject(parent)
        , m_backend(parent)
{
    updateDeviceList();
}

/**
 * Clears all the device lists before destroying.
 */
DeviceManager::~DeviceManager()
{
    m_audioCaptureDeviceList.clear();
    m_videoCaptureDeviceList.clear();
    m_audioOutputDeviceList.clear();
}

/**
 * \return True if the device can be opened.
 */
bool DeviceManager::canOpenDevice() const
{
    return true;
}

/**
 * Searches for the device in the device lists, by comparing it's name
 *
 * \param name Name identifier for the device to search for
 * \return A positive device id or -1 if device does not exist.
 */
int DeviceManager::deviceId(const QByteArray &name) const
{
    for (int i = 0 ; i < m_audioCaptureDeviceList.size() ; ++i) {
        if (m_audioCaptureDeviceList[i].name == name)
            return m_audioCaptureDeviceList[i].id;
    }

    for (int i = 0 ; i < m_videoCaptureDeviceList.size() ; ++i) {
        if (m_videoCaptureDeviceList[i].name == name)
            return m_videoCaptureDeviceList[i].id;
    }

    for (int i = 0 ; i < m_audioOutputDeviceList.size() ; ++i) {
        if (m_audioOutputDeviceList[i].name == name)
            return m_audioOutputDeviceList[i].id;
    }

    return -1;
}

/**
 * Get a human-readable description from a device id.
 * \param i_id Device identifier
 */
QString DeviceManager::deviceDescription(int i_id) const
{
    for (int i = 0 ; i < m_audioCaptureDeviceList.size() ; ++i) {
        if (m_audioCaptureDeviceList[i].id == i_id)
            return m_audioCaptureDeviceList[i].description;
    }

    for (int i = 0 ; i < m_videoCaptureDeviceList.size() ; ++i) {
        if (m_videoCaptureDeviceList[i].id == i_id)
            return m_videoCaptureDeviceList[i].description;
    }

    for (int i = 0 ; i < m_audioOutputDeviceList.size() ; ++i) {
        if (m_audioOutputDeviceList[i].id == i_id)
            return m_audioOutputDeviceList[i].description;
    }

    return QByteArray();
}

/** \internal
 * Compares the list with the devices available at the moment with the last list. If
 * a new device is seen, a signal is emitted. If a device dissapeared, another signal
 * is emitted. The devices are only from one category (example audio output devices).
 *
 * \param newDevices The list for the devices currently available
 * \param deviceList The old device list
 *
 * \see deviceAdded
 * \see deviceRemoved
 */
void DeviceManager::updateDeviceSublist(const QList<DeviceInfo> &newDevices, QList<DeviceInfo> &deviceList)
{
    // New and old device counts
    int ndc = newDevices.count();
    int odc = deviceList.count();

    for (int i = 0 ; i < ndc ; ++i) {
        if (deviceId(newDevices[i].name) == -1) {
            // This is a new device, add it
            deviceList.append(newDevices[i]);
            emit deviceAdded(deviceId(newDevices[i].name));
            qDebug() << "added device " << newDevices[i].name.data() << "id" << deviceId(newDevices[i].name);
        }
    }

    if (ndc < odc) {
        // A device was removed
        for (int i = odc - 1; i >= 0 ; --i) {
            QByteArray currId = deviceList[i].name;
            bool b_found = false;
            for (int k = ndc - 1; k >= 0 ; --k) {
                if (currId == newDevices[k].name) {
                    b_found = true;
                    break;
                }
            }
            if (!b_found) {
                emit deviceRemoved(deviceId(currId));
                deviceList.removeAt(i);
            }
        }
    }
}

/**
 * Update the current list of active devices. It probes for audio output devices,
 * audio capture devices, video capture devices. The methods depend on the
 * device types.
 */
void DeviceManager::updateDeviceList()
{
    // Lists for capture devices
    QList<DeviceInfo> devices, vcs, acs;
    int i;

    // Get the list of available capture devices
    scanDevices(devices);

    // See the device capabilities and sort them accordingly
    for (i = 0; i < devices.count(); ++ i) {
        if (devices[i].capabilities & DeviceInfo::VideoCapture)
            vcs << devices[i];
        if (devices[i].capabilities & DeviceInfo::AudioCapture)
            acs << devices[i];
    }

    devices.clear();

    // Update the capture device lists
    updateDeviceSublist(vcs, m_videoCaptureDeviceList);
    updateDeviceSublist(acs, m_audioCaptureDeviceList);

    // Lists for audio output devices
    QList<DeviceInfo> aos;
    aos.append(DeviceInfo("default"));
    aos.last().capabilities = DeviceInfo::AudioOutput;

    // Get the list of available audio outputs
    libvlc_audio_output_t *p_ao_list = libvlc_audio_output_list_get(vlc_instance);
    if(!p_ao_list)
        qDebug() << "libvlc exception:" << libvlc_errmsg();
    libvlc_audio_output_t *p_start = p_ao_list;

    bool checkpulse = false;
#ifdef PHONON_PULSESUPPORT
    PulseSupport *pulse = PulseSupport::getInstance();
    checkpulse = pulse->isActive();
#endif
    bool haspulse = false;
    while (p_ao_list) {
        if (checkpulse && 0 == strcmp(p_ao_list->psz_name, "pulse")) {
            aos.last().accessList.append(DeviceAccess("PULSE", "default"));
            haspulse = true;
            break;
        }

        aos.append(DeviceInfo(p_ao_list->psz_name));
        aos.last().accessList.append(DeviceAccess("?", p_ao_list->psz_name));
        aos.last().capabilities = DeviceInfo::AudioOutput;

        p_ao_list = p_ao_list->p_next;
    }
    libvlc_audio_output_list_release(p_start);

#ifdef PHONON_PULSESUPPORT
    if (haspulse)
        return;
    pulse->enable(false);
#endif

    updateDeviceSublist(aos, m_audioOutputDeviceList);
}

/**
* Return a list of name identifiers for audio capture devices.
*/
const QList<DeviceInfo> DeviceManager::audioCaptureDevices() const
{
    return m_audioCaptureDeviceList;
}

/**
* Return a list of name identifiers for video capture devices.
*/
const QList<DeviceInfo> DeviceManager::videoCaptureDevices() const
{
    return m_videoCaptureDeviceList;
}

/**
 * Return a list of name identifiers for audio output devices.
 */
const QList<DeviceInfo> DeviceManager::audioOutputDevices() const
{
    return m_audioOutputDeviceList;
}

}
}

QT_END_NAMESPACE
<commit_msg>Change driver name for Pulse to lower case<commit_after>/*****************************************************************************
 * libVLC backend for the Phonon library                                     *
 *                                                                           *
 * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
 * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
 * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
 * Copyright (C) 2009-2010 vlc-phonon AUTHORS                                *
 *                                                                           *
 * This program is free software; you can redistribute it and/or             *
 * modify it under the terms of the GNU Lesser General Public                *
 * License as published by the Free Software Foundation; either              *
 * version 2.1 of the License, or (at your option) any later version.        *
 *                                                                           *
 * This program is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 * Lesser General Public License for more details.                           *
 *                                                                           *
 * You should have received a copy of the GNU Lesser General Public          *
 * License along with this package; if not, write to the Free Software       *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 *****************************************************************************/

#include "devicemanager.h"
#include "devicescan.h"
#include "backend.h"
//#include "videowidget.h"
//#include "widgetrenderer.h"
#include "vlcloader.h"

#ifdef PHONON_PULSESUPPORT
#  include <phonon/pulsesupport.h>
#endif

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace VLC {

/**
 * Constructs a device info object and sets it's device identifiers.
 */
DeviceInfo::DeviceInfo( const QByteArray& name, const QString& description)
{
    // Get an id
    static int counter = 0;
    id = counter++;

    // Get name and description for the device
    this->name = name;
    this->description = description;
    capabilities = None;
}

/**
 * Constructs a device manager and immediately updates the device lists.
 */
DeviceManager::DeviceManager(Backend *parent)
        : QObject(parent)
        , m_backend(parent)
{
    updateDeviceList();
}

/**
 * Clears all the device lists before destroying.
 */
DeviceManager::~DeviceManager()
{
    m_audioCaptureDeviceList.clear();
    m_videoCaptureDeviceList.clear();
    m_audioOutputDeviceList.clear();
}

/**
 * \return True if the device can be opened.
 */
bool DeviceManager::canOpenDevice() const
{
    return true;
}

/**
 * Searches for the device in the device lists, by comparing it's name
 *
 * \param name Name identifier for the device to search for
 * \return A positive device id or -1 if device does not exist.
 */
int DeviceManager::deviceId(const QByteArray &name) const
{
    for (int i = 0 ; i < m_audioCaptureDeviceList.size() ; ++i) {
        if (m_audioCaptureDeviceList[i].name == name)
            return m_audioCaptureDeviceList[i].id;
    }

    for (int i = 0 ; i < m_videoCaptureDeviceList.size() ; ++i) {
        if (m_videoCaptureDeviceList[i].name == name)
            return m_videoCaptureDeviceList[i].id;
    }

    for (int i = 0 ; i < m_audioOutputDeviceList.size() ; ++i) {
        if (m_audioOutputDeviceList[i].name == name)
            return m_audioOutputDeviceList[i].id;
    }

    return -1;
}

/**
 * Get a human-readable description from a device id.
 * \param i_id Device identifier
 */
QString DeviceManager::deviceDescription(int i_id) const
{
    for (int i = 0 ; i < m_audioCaptureDeviceList.size() ; ++i) {
        if (m_audioCaptureDeviceList[i].id == i_id)
            return m_audioCaptureDeviceList[i].description;
    }

    for (int i = 0 ; i < m_videoCaptureDeviceList.size() ; ++i) {
        if (m_videoCaptureDeviceList[i].id == i_id)
            return m_videoCaptureDeviceList[i].description;
    }

    for (int i = 0 ; i < m_audioOutputDeviceList.size() ; ++i) {
        if (m_audioOutputDeviceList[i].id == i_id)
            return m_audioOutputDeviceList[i].description;
    }

    return QByteArray();
}

/** \internal
 * Compares the list with the devices available at the moment with the last list. If
 * a new device is seen, a signal is emitted. If a device dissapeared, another signal
 * is emitted. The devices are only from one category (example audio output devices).
 *
 * \param newDevices The list for the devices currently available
 * \param deviceList The old device list
 *
 * \see deviceAdded
 * \see deviceRemoved
 */
void DeviceManager::updateDeviceSublist(const QList<DeviceInfo> &newDevices, QList<DeviceInfo> &deviceList)
{
    // New and old device counts
    int ndc = newDevices.count();
    int odc = deviceList.count();

    for (int i = 0 ; i < ndc ; ++i) {
        if (deviceId(newDevices[i].name) == -1) {
            // This is a new device, add it
            deviceList.append(newDevices[i]);
            emit deviceAdded(deviceId(newDevices[i].name));
            qDebug() << "added device " << newDevices[i].name.data() << "id" << deviceId(newDevices[i].name);
        }
    }

    if (ndc < odc) {
        // A device was removed
        for (int i = odc - 1; i >= 0 ; --i) {
            QByteArray currId = deviceList[i].name;
            bool b_found = false;
            for (int k = ndc - 1; k >= 0 ; --k) {
                if (currId == newDevices[k].name) {
                    b_found = true;
                    break;
                }
            }
            if (!b_found) {
                emit deviceRemoved(deviceId(currId));
                deviceList.removeAt(i);
            }
        }
    }
}

/**
 * Update the current list of active devices. It probes for audio output devices,
 * audio capture devices, video capture devices. The methods depend on the
 * device types.
 */
void DeviceManager::updateDeviceList()
{
    // Lists for capture devices
    QList<DeviceInfo> devices, vcs, acs;
    int i;

    // Get the list of available capture devices
    scanDevices(devices);

    // See the device capabilities and sort them accordingly
    for (i = 0; i < devices.count(); ++ i) {
        if (devices[i].capabilities & DeviceInfo::VideoCapture)
            vcs << devices[i];
        if (devices[i].capabilities & DeviceInfo::AudioCapture)
            acs << devices[i];
    }

    devices.clear();

    // Update the capture device lists
    updateDeviceSublist(vcs, m_videoCaptureDeviceList);
    updateDeviceSublist(acs, m_audioCaptureDeviceList);

    // Lists for audio output devices
    QList<DeviceInfo> aos;
    aos.append(DeviceInfo("default"));
    aos.last().capabilities = DeviceInfo::AudioOutput;

    // Get the list of available audio outputs
    libvlc_audio_output_t *p_ao_list = libvlc_audio_output_list_get(vlc_instance);
    if(!p_ao_list)
        qDebug() << "libvlc exception:" << libvlc_errmsg();
    libvlc_audio_output_t *p_start = p_ao_list;

    bool checkpulse = false;
#ifdef PHONON_PULSESUPPORT
    PulseSupport *pulse = PulseSupport::getInstance();
    checkpulse = pulse->isActive();
#endif
    bool haspulse = false;
    while (p_ao_list) {
        if (checkpulse && 0 == strcmp(p_ao_list->psz_name, "pulse")) {
            aos.last().accessList.append(DeviceAccess("pulse", "default"));
            haspulse = true;
            break;
        }

        aos.append(DeviceInfo(p_ao_list->psz_name));
        aos.last().accessList.append(DeviceAccess("?", p_ao_list->psz_name));
        aos.last().capabilities = DeviceInfo::AudioOutput;

        p_ao_list = p_ao_list->p_next;
    }
    libvlc_audio_output_list_release(p_start);

#ifdef PHONON_PULSESUPPORT
    if (haspulse)
        return;
    pulse->enable(false);
#endif

    updateDeviceSublist(aos, m_audioOutputDeviceList);
}

/**
* Return a list of name identifiers for audio capture devices.
*/
const QList<DeviceInfo> DeviceManager::audioCaptureDevices() const
{
    return m_audioCaptureDeviceList;
}

/**
* Return a list of name identifiers for video capture devices.
*/
const QList<DeviceInfo> DeviceManager::videoCaptureDevices() const
{
    return m_videoCaptureDeviceList;
}

/**
 * Return a list of name identifiers for audio output devices.
 */
const QList<DeviceInfo> DeviceManager::audioOutputDevices() const
{
    return m_audioOutputDeviceList;
}

}
}

QT_END_NAMESPACE
<|endoftext|>