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(); }
// 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; }
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(); }
// 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); }
// 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); }
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); }
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; }
// 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; }
// 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); } }
/// \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; }
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; }
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; }
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); }