Пример #1
0
StructuredData::ObjectSP
StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
  if (this->GetType() == lldb::eStructuredDataTypeDictionary) {
    std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
    std::string key = match.first.str();
    ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
    if (value.get()) {
      // Do we have additional words to descend?  If not, return the value
      // we're at right now.
      if (match.second.empty()) {
        return value;
      } else {
        return value->GetObjectForDotSeparatedPath(match.second);
      }
    }
    return ObjectSP();
  }

  if (this->GetType() == lldb::eStructuredDataTypeArray) {
    std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
    if (match.second.empty()) {
      return this->shared_from_this();
    }
    errno = 0;
    uint64_t val = strtoul(match.second.str().c_str(), nullptr, 10);
    if (errno == 0) {
      return this->GetAsArray()->GetItemAtIndex(val);
    }
    return ObjectSP();
  }

  return this->shared_from_this();
}
Пример #2
0
// Parses the contents of version.txt in an CUDA installation.  It should
// contain one line of the from e.g. "CUDA Version 7.5.2".
static CudaVersion ParseCudaVersionFile(llvm::StringRef V) {
  if (!V.startswith("CUDA Version "))
    return CudaVersion::UNKNOWN;
  V = V.substr(strlen("CUDA Version "));
  int Major = -1, Minor = -1;
  auto First = V.split('.');
  auto Second = First.second.split('.');
  if (First.first.getAsInteger(10, Major) ||
      Second.first.getAsInteger(10, Minor))
    return CudaVersion::UNKNOWN;

  if (Major == 7 && Minor == 0) {
    // This doesn't appear to ever happen -- version.txt doesn't exist in the
    // CUDA 7 installs I've seen.  But no harm in checking.
    return CudaVersion::CUDA_70;
  }
  if (Major == 7 && Minor == 5)
    return CudaVersion::CUDA_75;
  if (Major == 8 && Minor == 0)
    return CudaVersion::CUDA_80;
  if (Major == 9 && Minor == 0)
    return CudaVersion::CUDA_90;
  if (Major == 9 && Minor == 1)
    return CudaVersion::CUDA_91;
  return CudaVersion::UNKNOWN;
}
Пример #3
0
lldb::OptionValueSP
OptionValueArray::GetSubValue(const ExecutionContext *exe_ctx,
                              llvm::StringRef name, bool will_modify,
                              Status &error) const {
  if (name.empty() || name.front() != '[') {
    error.SetErrorStringWithFormat(
      "invalid value path '%s', %s values only support '[<index>]' subvalues "
      "where <index> is a positive or negative array index",
      name.str().c_str(), GetTypeAsCString());
    return nullptr;
  }

  name = name.drop_front();
  llvm::StringRef index, sub_value;
  std::tie(index, sub_value) = name.split(']');
  if (index.size() == name.size()) {
    // Couldn't find a closing bracket
    return nullptr;
  }

  const size_t array_count = m_values.size();
  int32_t idx = 0;
  if (index.getAsInteger(0, idx))
    return nullptr;

  uint32_t new_idx = UINT32_MAX;
  if (idx < 0) {
    // Access from the end of the array if the index is negative
    new_idx = array_count - idx;
  } else {
    // Just a standard index
    new_idx = idx;
  }

  if (new_idx < array_count) {
    if (m_values[new_idx]) {
      if (!sub_value.empty())
        return m_values[new_idx]->GetSubValue(exe_ctx, sub_value,
                                              will_modify, error);
      else
        return m_values[new_idx];
    }
  } else {
    if (array_count == 0)
      error.SetErrorStringWithFormat(
          "index %i is not valid for an empty array", idx);
    else if (idx > 0)
      error.SetErrorStringWithFormat(
          "index %i out of range, valid values are 0 through %" PRIu64,
          idx, (uint64_t)(array_count - 1));
    else
      error.SetErrorStringWithFormat("negative index %i out of range, "
                                      "valid values are -1 through "
                                      "-%" PRIu64,
                                      idx, (uint64_t)array_count);
  }
  return OptionValueSP();
}
Пример #4
0
// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
                            llvm::StringRef CPUName, llvm::StringRef ArchName,
                            std::vector<StringRef> &Features,
                            const llvm::Triple &Triple) {
  std::pair<StringRef, StringRef> Split = CPUName.split("+");

  std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
  if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() ||
      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
Пример #5
0
// Check if -march is valid by checking if it can be canonicalised and parsed.
// getARMArch is used here instead of just checking the -march value in order
// to handle -march=native correctly.
static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
                             llvm::StringRef ArchName,
                             std::vector<StringRef> &Features,
                             const llvm::Triple &Triple) {
  std::pair<StringRef, StringRef> Split = ArchName.split("+");

  std::string MArch = arm::getARMArch(ArchName, Triple);
  if (llvm::ARM::parseArch(MArch) == llvm::ARM::ArchKind::INVALID ||
      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
Пример #6
0
static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle,
                           llvm::StringRef Repl) {
  std::string Result;
  llvm::raw_string_ostream OS(Result);
  std::pair<llvm::StringRef, llvm::StringRef> Split;
  for (Split = Haystack.split(Needle); !Split.second.empty();
       Split = Split.first.split(Needle))
    OS << Split.first << Repl;
  Result += Split.first;
  OS.flush();
  return Result;
}
lldb::OptionValueSP
OptionValueDictionary::GetSubValue(const ExecutionContext *exe_ctx,
                                   llvm::StringRef name, bool will_modify,
                                   Status &error) const {
  lldb::OptionValueSP value_sp;
  if (name.empty())
    return nullptr;

  llvm::StringRef left, temp;
  std::tie(left, temp) = name.split('[');
  if (left.size() == name.size()) {
    error.SetErrorStringWithFormat("invalid value path '%s', %s values only "
      "support '[<key>]' subvalues where <key> "
      "a string value optionally delimited by "
      "single or double quotes",
      name.str().c_str(), GetTypeAsCString());
    return nullptr;
  }
  assert(!temp.empty());

  llvm::StringRef key, quote_char;

  if (temp[0] == '\"' || temp[0] == '\'') {
    quote_char = temp.take_front();
    temp = temp.drop_front();
  }

  llvm::StringRef sub_name;
  std::tie(key, sub_name) = temp.split(']');

  if (!key.consume_back(quote_char) || key.empty()) {
    error.SetErrorStringWithFormat("invalid value path '%s', "
      "key names must be formatted as ['<key>'] where <key> "
      "is a string that doesn't contain quotes and the quote"
      " char is optional", name.str().c_str());
    return nullptr;
  }

  value_sp = GetValueForKey(ConstString(key));
  if (!value_sp) {
    error.SetErrorStringWithFormat(
      "dictionary does not contain a value for the key name '%s'",
      key.str().c_str());
    return nullptr;
  }

  if (sub_name.empty())
    return value_sp;
  return value_sp->GetSubValue(exe_ctx, sub_name, will_modify, error);
}
Пример #8
0
Version Version::getFromString(llvm::StringRef VersionStr) {
  llvm::StringRef MajorStr, MinorStr;
  Version V;

  std::tie(MajorStr, MinorStr) = VersionStr.split('.');
  if (!MinorStr.empty()) {
    llvm::StringRef Ignore;
    std::tie(MinorStr, Ignore) = MinorStr.split('.');
    if (MinorStr.getAsInteger(10, V.Minor))
      return Version();
  }
  if (MajorStr.getAsInteger(10, V.Major))
    return Version();
  return V;
}
Пример #9
0
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
static llvm::StringRef
removeHostnameFromPathname(llvm::StringRef path_from_dwarf) {
  llvm::StringRef host, path;
  std::tie(host, path) = path_from_dwarf.split(':');

  if (host.contains('/'))
    return path_from_dwarf;

  // check whether we have a windows path, and so the first character is a
  // drive-letter not a hostname.
  if (host.size() == 1 && llvm::isAlpha(host[0]) && path.startswith("\\"))
    return path_from_dwarf;

  return path;
}
Пример #10
0
// Append a #define line to Buf for Macro.  Macro should be of the form XXX,
// in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit
// "#define XXX Y z W".  To get a #define with no value, use "XXX=".
static void DefineBuiltinMacro(MacroBuilder &Builder, llvm::StringRef Macro,
                               Diagnostic &Diags) {
  std::pair<llvm::StringRef, llvm::StringRef> MacroPair = Macro.split('=');
  llvm::StringRef MacroName = MacroPair.first;
  llvm::StringRef MacroBody = MacroPair.second;
  if (MacroName.size() != Macro.size()) {
    // Per GCC -D semantics, the macro ends at \n if it exists.
    llvm::StringRef::size_type End = MacroBody.find_first_of("\n\r");
    if (End != llvm::StringRef::npos)
      Diags.Report(diag::warn_fe_macro_contains_embedded_newline)
        << MacroName;
    Builder.defineMacro(MacroName, MacroBody.substr(0, End));
  } else {
    // Push "macroname 1".
    Builder.defineMacro(Macro);
  }
}
Пример #11
0
/// \brief Parse the simulator version define:
/// __IPHONE_OS_VERSION_MIN_REQUIRED=([0-9])([0-9][0-9])([0-9][0-9])
// and return the grouped values as integers, e.g:
//   __IPHONE_OS_VERSION_MIN_REQUIRED=40201
// will return Major=4, Minor=2, Micro=1.
static bool GetVersionFromSimulatorDefine(llvm::StringRef define,
                                          unsigned &Major, unsigned &Minor,
                                          unsigned &Micro) {
  assert(define.startswith(SimulatorVersionDefineName()));
  llvm::StringRef name, version;
  llvm::tie(name, version) = define.split('=');
  if (version.empty())
    return false;
  std::string verstr = version.str();
  char *end;
  unsigned num = (unsigned) strtol(verstr.c_str(), &end, 10);
  if (*end != '\0')
    return false;
  Major = num / 10000;
  num = num % 10000;
  Minor = num / 100;
  Micro = num % 100;
  return true;
}
Пример #12
0
bool SplitPaths(llvm::StringRef PathStr,
                llvm::SmallVectorImpl<llvm::StringRef>& Paths,
                SplitMode Mode, llvm::StringRef Delim, bool Verbose) {
  assert(Delim.size() && "Splitting without a delimiter");

#if defined(LLVM_ON_WIN32)
  // Support using a ':' delimiter on Windows.
  const bool WindowsColon = Delim.equals(":");
#endif

  bool AllExisted = true;
  for (std::pair<llvm::StringRef, llvm::StringRef> Split = PathStr.split(Delim);
       !Split.second.empty(); Split = PathStr.split(Delim)) {

    if (!Split.first.empty()) {
      bool Exists = llvm::sys::fs::is_directory(Split.first);

#if defined(LLVM_ON_WIN32)
    // Because drive letters will have a colon we have to make sure the split
    // occurs at a colon not followed by a path separator.
    if (!Exists && WindowsColon && Split.first.size()==1) {
      // Both clang and cl.exe support '\' and '/' path separators.
      if (Split.second.front() == '\\' || Split.second.front() == '/') {
          const std::pair<llvm::StringRef, llvm::StringRef> Tmp =
              Split.second.split(Delim);
          // Split.first = 'C', but we want 'C:', so Tmp.first.size()+2
          Split.first =
              llvm::StringRef(Split.first.data(), Tmp.first.size() + 2);
          Split.second = Tmp.second;
          Exists = llvm::sys::fs::is_directory(Split.first);
      }
    }
#endif

      AllExisted = AllExisted && Exists;

      if (!Exists) {
        if (Mode == kFailNonExistant) {
          if (Verbose) {
            // Exiting early, but still log all non-existant paths that we have
            LogNonExistantDirectory(Split.first);
            while (!Split.second.empty()) {
              Split = PathStr.split(Delim);
              if (llvm::sys::fs::is_directory(Split.first)) {
                llvm::errs() << "  ignoring directory that exists \""
                             << Split.first << "\"\n";
              } else
                LogNonExistantDirectory(Split.first);
              Split = Split.second.split(Delim);
            }
            if (!llvm::sys::fs::is_directory(Split.first))
              LogNonExistantDirectory(Split.first);
          }
          return false;
        } else if (Mode == kAllowNonExistant)
          Paths.push_back(Split.first);
        else if (Verbose)
          LogNonExistantDirectory(Split.first);
      } else
        Paths.push_back(Split.first);
    }

    PathStr = Split.second;
  }

  // Trim trailing sep in case of A:B:C:D:
  if (!PathStr.empty() && PathStr.endswith(Delim))
    PathStr = PathStr.substr(0, PathStr.size()-Delim.size());

  if (!PathStr.empty()) {
    if (!llvm::sys::fs::is_directory(PathStr)) {
      AllExisted = false;
      if (Mode == kAllowNonExistant)
        Paths.push_back(PathStr);
      else if (Verbose)
        LogNonExistantDirectory(PathStr);
    } else
      Paths.push_back(PathStr);
  }

  return AllExisted;
}
Пример #13
0
std::vector<find_all_symbols::SymbolInfo>
SymbolIndexManager::search(llvm::StringRef Identifier,
                           bool IsNestedSearch) const {
  // The identifier may be fully qualified, so split it and get all the context
  // names.
  llvm::SmallVector<llvm::StringRef, 8> Names;
  Identifier.split(Names, "::");

  bool IsFullyQualified = false;
  if (Identifier.startswith("::")) {
    Names.erase(Names.begin()); // Drop first (empty) element.
    IsFullyQualified = true;
  }

  // As long as we don't find a result keep stripping name parts from the end.
  // This is to support nested classes which aren't recorded in the database.
  // Eventually we will either hit a class (namespaces aren't in the database
  // either) and can report that result.
  bool TookPrefix = false;
  std::vector<clang::find_all_symbols::SymbolInfo> MatchedSymbols;
  do {
    std::vector<clang::find_all_symbols::SymbolInfo> Symbols;
    for (const auto &DB : SymbolIndices) {
      auto Res = DB->search(Names.back().str());
      Symbols.insert(Symbols.end(), Res.begin(), Res.end());
    }

    DEBUG(llvm::dbgs() << "Searching " << Names.back() << "... got "
                       << Symbols.size() << " results...\n");

    for (const auto &Symbol : Symbols) {
      // Match the identifier name without qualifier.
      if (Symbol.getName() == Names.back()) {
        bool IsMatched = true;
        auto SymbolContext = Symbol.getContexts().begin();
        auto IdentiferContext = Names.rbegin() + 1; // Skip identifier name.
        // Match the remaining context names.
        while (IdentiferContext != Names.rend() &&
               SymbolContext != Symbol.getContexts().end()) {
          if (SymbolContext->second == *IdentiferContext) {
            ++IdentiferContext;
            ++SymbolContext;
          } else if (SymbolContext->first ==
                     find_all_symbols::SymbolInfo::ContextType::EnumDecl) {
            // Skip non-scoped enum context.
            ++SymbolContext;
          } else {
            IsMatched = false;
            break;
          }
        }

        // If the name was qualified we only want to add results if we evaluated
        // all contexts.
        if (IsFullyQualified)
          IsMatched &= (SymbolContext == Symbol.getContexts().end());

        // FIXME: Support full match. At this point, we only find symbols in
        // database which end with the same contexts with the identifier.
        if (IsMatched && IdentiferContext == Names.rend()) {
          // If we're in a situation where we took a prefix but the thing we
          // found couldn't possibly have a nested member ignore it.
          if (TookPrefix &&
              (Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Function ||
               Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Variable ||
               Symbol.getSymbolKind() ==
                   SymbolInfo::SymbolKind::EnumConstantDecl ||
               Symbol.getSymbolKind() == SymbolInfo::SymbolKind::Macro))
            continue;

          MatchedSymbols.push_back(Symbol);
        }
      }
    }
    Names.pop_back();
    TookPrefix = true;
  } while (MatchedSymbols.empty() && !Names.empty() && IsNestedSearch);

  rankByPopularity(MatchedSymbols);
  return MatchedSymbols;
}
Пример #14
0
void
NasmInsnRunner::ParseAndTestLine(const char* filename,
                                 const llvm::StringRef& line,
                                 int linenum)
{
    SCOPED_TRACE(llvm::format("%s:%d", filename, linenum));

    llvm::StringRef insn_in, golden_in;
    llvm::tie(insn_in, golden_in) = line.split(';');

    insn_in = strip(insn_in);
    golden_in = strip(golden_in);

    // Handle bits directive
    if (golden_in.empty() && insn_in.startswith("[bits "))
    {
        int bits = atoi(insn_in.substr(6, 2).str().c_str());
        if (bits == 64)
            m_arch->setMachine("amd64");
        else
            m_arch->setMachine("x86");
        m_arch->setVar("mode_bits", bits);
        return;
    }

    if (insn_in.empty() || golden_in.empty())
        return;     // skip lines that don't have both text and a comment

    //
    // parse the golden result
    //
    llvm::SmallVector<unsigned char, 64> golden;
    llvm::StringRef golden_errwarn;

    for (;;)
    {
        // strip whitespace
        golden_in = strip(golden_in);
        if (golden_in.empty() || !isxdigit(golden_in[0]))
            break;

        unsigned int byte_val = 0x100;
        llvm::StringRef byte_str;
        llvm::tie(byte_str, golden_in) = golden_in.split(' ');

        if (byte_str.size() == 2)   // assume hex
            byte_val = (fromhexdigit(byte_str[0]) << 4)
                | fromhexdigit(byte_str[1]);
        else if (byte_str.size() == 3)  // assume octal
            byte_val = (fromoctdigit(byte_str[0]) << 6)
                | (fromoctdigit(byte_str[1]) << 3)
                | fromoctdigit(byte_str[2]);

        ASSERT_LE(byte_val, 0xffU) << "invalid golden value";
        golden.push_back(byte_val);
    }

    // interpret string in [] as error/warning
    if (!golden_in.empty() && golden_in[0] == '[')
        llvm::tie(golden_errwarn, golden_in) = golden_in.substr(1).split(']');

    //
    // parse the instruction
    //
    ::testing::StrictMock<MockDiagnosticString> mock_consumer;
    llvm::IntrusiveRefCntPtr<DiagnosticIDs> diagids(new DiagnosticIDs);
    DiagnosticsEngine diags(diagids, &mock_consumer, false);
    FileSystemOptions opts;
    FileManager fmgr(opts);
    SourceManager smgr(diags, fmgr);
    diags.setSourceManager(&smgr);

    // instruction name is the first thing on the line
    llvm::StringRef insn_name;
    llvm::tie(insn_name, insn_in) = insn_in.split(' ');
    Arch::InsnPrefix insnprefix =
        m_arch->ParseCheckInsnPrefix(insn_name, SourceLocation(), diags);
    ASSERT_TRUE(insnprefix.isType(Arch::InsnPrefix::INSN));
    std::auto_ptr<Insn> insn = m_arch->CreateInsn(insnprefix.getInsn());
    ASSERT_TRUE(insn.get() != 0) << "unrecognized instruction '"
        << insn_name.str() << "'";

    // parse insn arguments
    unsigned int wsize = m_arch_module->getWordSize();

    // strip whitespace from arguments
    insn_in = strip(insn_in);

    while (!insn_in.empty())
    {
        llvm::StringRef arg_str;
        llvm::tie(arg_str, insn_in) = insn_in.split(',');

        // strip whitespace from arg
        arg_str = strip(arg_str);

        unsigned int size = 0;
        bool strict = false;
        for (;;)
        {
            int next;
            int nsize = 0;
            // operand overrides (size and strict)
            if (arg_str.startswith("byte ")) { nsize = 8; next = 5; }
            else if (arg_str.startswith("hword ")) { nsize = wsize/2; next = 6; }
            else if (arg_str.startswith("word ")) { nsize = wsize; next = 5; }
            else if (arg_str.startswith("dword ")) { nsize = wsize*2; next = 6; }
            else if (arg_str.startswith("qword ")) { nsize = wsize*4; next = 6; }
            else if (arg_str.startswith("tword ")) { nsize = 80; next = 6; }
            else if (arg_str.startswith("dqword ")) { nsize = wsize*8; next = 7; }
            else if (arg_str.startswith("oword ")) { nsize = wsize*8; next = 6; }
            else if (arg_str.startswith("yword ")) { nsize = 256; next = 6; }
            else if (arg_str.startswith("strict ")) { strict = true; next = 7; }
            else break;

            if (size == 0)
                size = nsize;
            arg_str = arg_str.substr(next);
        }

        if (arg_str[0] == '[')
        {
            // Very simple int/reg expression parser.  Does not handle parens or
            // order of operations; simply builds expr from left to right.
            // This means r8*4+r9 will have a different result than r9+r8*4!
            // Also only handles binary operators * and +.
            llvm::StringRef estr = arg_str.slice(1, arg_str.find(']')+1);
            std::auto_ptr<Expr> e(new Expr);

            char pendingop = '\0';
            std::size_t tokstart = 0;
            for (std::size_t pos = 0; pos < estr.size(); ++pos)
            {
                if (estr[pos] == '*' || estr[pos] == '+' || estr[pos] == ']')
                {
                    // figure out this token
                    llvm::StringRef tok = strip(estr.slice(tokstart, pos));
                    if (isdigit(estr[tokstart]))
                        e->Append(strtoint(tok));
                    else
                    {
                        Arch::RegTmod regtmod =
                            m_arch->ParseCheckRegTmod(tok,
                                                      SourceLocation(),
                                                      diags);
                        ASSERT_TRUE(regtmod.isType(Arch::RegTmod::REG))
                            << "cannot handle label '" << tok.str() << "'";
                        e->Append(*regtmod.getReg());
                    }

                    // append pending operator
                    if (pendingop == '*')
                        e->AppendOp(Op::MUL, 2);
                    else if (pendingop == '+')
                        e->AppendOp(Op::ADD, 2);

                    // store new operator
                    pendingop = estr[pos];
                    tokstart = pos+1;
                }
            }

            Operand operand(m_arch->CreateEffAddr(e));
            operand.setSize(size);
            operand.setStrict(strict);
            insn->AddOperand(operand);
            continue;
        }

        // TODO: split by space to allow target modifiers

        // Test for registers
        Arch::RegTmod regtmod =
            m_arch->ParseCheckRegTmod(arg_str, SourceLocation(), diags);
        if (const Register* reg = regtmod.getReg())
        {
            Operand operand(reg);
            operand.setSize(size);
            operand.setStrict(strict);
            insn->AddOperand(operand);
            continue;
        }
        else if (const SegmentRegister* segreg = regtmod.getSegReg())
        {
            Operand operand(segreg);
            operand.setSize(size);
            operand.setStrict(strict);
            insn->AddOperand(operand);
            continue;
        }
        else if (regtmod.getTargetMod())
        {
            FAIL() << "cannot handle target modifier";
        }
        else if (regtmod.getRegGroup())
        {
            FAIL() << "cannot handle register group";
        }

        // Can't handle labels
        ASSERT_TRUE(isdigit(arg_str[0]) || arg_str[0] == '-')
            << "cannot handle label '" << arg_str.str() << "'";

        // Convert to integer expression
        Operand intop(Expr::Ptr(new Expr(strtoint(arg_str))));
        intop.setSize(size);
        intop.setStrict(strict);
        insn->AddOperand(intop);
    }

    TestInsn(insn.get(), golden.size(), golden.data(), golden_errwarn);
}