PartOfSpeech swift::getPartOfSpeech(StringRef word) { // FIXME: This implementation is woefully inefficient. #define PREPOSITION(Word) \ if (word.equals_lower(#Word)) \ return PartOfSpeech::Preposition; #define VERB(Word) \ if (word.equals_lower(#Word)) \ return PartOfSpeech::Verb; #include "PartsOfSpeech.def" // Identify gerunds, which always end in "ing". if (word.endswith("ing") && word.size() > 4) { StringRef possibleVerb = word.substr(0, word.size()-3); // If what remains is a verb, we have a gerund. if (getPartOfSpeech(possibleVerb) == PartOfSpeech::Verb) return PartOfSpeech::Gerund; // Try adding an "e" and look for that as a verb. if (possibleVerb.back() != 'e') { SmallString<16> possibleVerbWithE; possibleVerbWithE += possibleVerb; possibleVerbWithE += 'e'; if (getPartOfSpeech(possibleVerbWithE) == PartOfSpeech::Verb) return PartOfSpeech::Gerund; } // If there is a repeated letter at the back, drop that second // instance of that letter and try again. unsigned count = possibleVerb.size(); if (possibleVerb[count-1] == possibleVerb[count-2] && getPartOfSpeech(possibleVerb.substr(0, count-1)) == PartOfSpeech::Verb) return PartOfSpeech::Gerund; } // "auto" tends to be used as a verb prefix. if (startsWithIgnoreFirstCase(word, "auto") && word.size() > 4) { if (getPartOfSpeech(word.substr(4)) == PartOfSpeech::Verb) return PartOfSpeech::Verb; } // "re" can prefix a verb. if (startsWithIgnoreFirstCase(word, "re") && word.size() > 2) { if (getPartOfSpeech(word.substr(2)) == PartOfSpeech::Verb) return PartOfSpeech::Verb; } // "de" can prefix a verb. if (startsWithIgnoreFirstCase(word, "de") && word.size() > 2) { if (getPartOfSpeech(word.substr(2)) == PartOfSpeech::Verb) return PartOfSpeech::Verb; } return PartOfSpeech::Unknown; }
/// Returns the common word-prefix of two strings, allowing the second string /// to be a common English plural form of the first. /// /// For example, given "NSProperty" and "NSProperties", the full "NSProperty" /// is returned. Given "NSMagicArmor" and "NSMagicArmory", only /// "NSMagic" is returned. /// /// The "-s", "-es", and "-ies" patterns cover every plural NS_OPTIONS name /// in Cocoa and Cocoa Touch. /// /// \see getCommonWordPrefix StringRef importer::getCommonPluralPrefix(StringRef singular, StringRef plural) { assert(!plural.empty()); if (singular.empty()) return singular; bool ignored; StringRef commonPrefix = getCommonWordPrefix(singular, plural, ignored); if (commonPrefix.size() == singular.size() || plural.back() != 's') return commonPrefix; StringRef leftover = singular.substr(commonPrefix.size()); StringRef firstLeftoverWord = camel_case::getFirstWord(leftover); StringRef commonPrefixPlusWord = singular.substr(0, commonPrefix.size() + firstLeftoverWord.size()); // Is the plural string just "[singular]s"? plural = plural.drop_back(); if (plural.endswith(firstLeftoverWord)) return commonPrefixPlusWord; if (plural.empty() || plural.back() != 'e') return commonPrefix; // Is the plural string "[singular]es"? plural = plural.drop_back(); if (plural.endswith(firstLeftoverWord)) return commonPrefixPlusWord; if (plural.empty() || !(plural.back() == 'i' && singular.back() == 'y')) return commonPrefix; // Is the plural string "[prefix]ies" and the singular "[prefix]y"? plural = plural.drop_back(); firstLeftoverWord = firstLeftoverWord.drop_back(); if (plural.endswith(firstLeftoverWord)) return commonPrefixPlusWord; return commonPrefix; }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer is actually a .s file, just emit the blob textually. // This is useful in case the asm parser doesn't handle something but the // system assembler does. if (OutStreamer.hasRawTextSupport()) { OutStreamer.EmitRawText(Str); return; } SourceMgr SrcMgr; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (void *DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler()) { SrcMgr.setDiagHandler((SourceMgr::DiagHandlerTy)(intptr_t)DiagHandler, LLVMCtx.getInlineAsmDiagnosticContext(), LocCookie); HasDiagHandler = true; } MemoryBuffer *Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); OwningPtr<MCAsmParser> Parser(createMCAsmParser(TM.getTarget(), SrcMgr, OutContext, OutStreamer, *MAI)); OwningPtr<TargetAsmParser> TAP(TM.getTarget().createAsmParser(*Parser, TM)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setTargetParser(*TAP.get()); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
void TemplateSpecializationType::PrintTemplateArgumentList( raw_ostream &OS, const TemplateArgument *Args, unsigned NumArgs, const PrintingPolicy &Policy, bool SkipBrackets) { if (!SkipBrackets) OS << '<'; bool needSpace = false; for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { if (Arg > 0) OS << ", "; // Print the argument into a string. SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); if (Args[Arg].getKind() == TemplateArgument::Pack) { PrintTemplateArgumentList(ArgOS, Args[Arg].pack_begin(), Args[Arg].pack_size(), Policy, true); } else { Args[Arg].print(Policy, ArgOS); } StringRef ArgString = ArgOS.str(); // If this is the first argument and its string representation // begins with the global scope specifier ('::foo'), add a space // to avoid printing the diagraph '<:'. if (!Arg && !ArgString.empty() && ArgString[0] == ':') OS << ' '; OS << ArgString; needSpace = (!ArgString.empty() && ArgString.back() == '>'); } // If the last character of our string is '>', add another space to // keep the two '>''s separate tokens. We don't *have* to do this in // C++0x, but it's still good hygiene. if (needSpace) OS << ' '; if (!SkipBrackets) OS << '>'; }
size_t QueryRequest::get_indices(StringRef name, IndexVec* indices) { set_has_names_for_values(true); if (value_names_.get_indices(name, indices) == 0) { if (value_names_.size() > elements_count()) { // No more space left for new named values return 0; } if (name.size() > 0 && name.front() == '"' && name.back() == '"') { name = name.substr(1, name.size() - 2); } indices->push_back(value_names_.add(ValueName(name.to_string()))); } return indices->size(); }
// Replace .. embedded in path for purposes of having // a canonical path. static std::string replaceDotDot(StringRef Path) { SmallString<128> Buffer; llvm::sys::path::const_iterator B = llvm::sys::path::begin(Path), E = llvm::sys::path::end(Path); while (B != E) { if (B->compare(".") == 0) { } else if (B->compare("..") == 0) llvm::sys::path::remove_filename(Buffer); else llvm::sys::path::append(Buffer, *B); ++B; } if (Path.endswith("/") || Path.endswith("\\")) Buffer.append(1, Path.back()); return Buffer.c_str(); }
/// Parse a stringified Swift declaration name, e.g. "init(frame:)". StringRef swift::parseDeclName(StringRef name, SmallVectorImpl<StringRef> &argumentLabels, bool &isFunctionName) { if (name.empty()) return ""; if (name.back() != ')') { isFunctionName = false; if (Lexer::isIdentifier(name) && name != "_") return name; return ""; } isFunctionName = true; StringRef BaseName, Parameters; std::tie(BaseName, Parameters) = name.split('('); if (!Lexer::isIdentifier(BaseName) || BaseName == "_") return ""; if (Parameters.empty()) return ""; Parameters = Parameters.drop_back(); // ')' if (Parameters.empty()) return BaseName; if (Parameters.back() != ':') return ""; do { StringRef NextParam; std::tie(NextParam, Parameters) = Parameters.split(':'); if (!Lexer::isIdentifier(NextParam)) return ""; if (NextParam == "_") argumentLabels.push_back(""); else argumentLabels.push_back(NextParam); } while (!Parameters.empty()); return BaseName; }
size_t CaseInsensitiveHashTable<T>::get_indices(StringRef name, IndexVec* result) const { result->clear(); bool is_case_sensitive = false; if (name.size() > 0 && name.front() == '"' && name.back() == '"') { is_case_sensitive = true; name = name.substr(1, name.size() - 2); } size_t h = fnv1a_hash_lower(name) & index_mask_; size_t start = h; while (index_[h] != NULL && !iequals(name, index_[h]->name)) { h = (h + 1) & index_mask_; if (h == start) { return 0; } } const T* entry = index_[h]; if (entry == NULL) { return 0; } if (!is_case_sensitive) { while (entry != NULL) { result->push_back(entry->index); entry = entry->next; } } else { while (entry != NULL) { if (name.equals(entry->name)) { result->push_back(entry->index); } entry = entry->next; } } return result->size(); }
/// Skip a type suffix that can be dropped. static Optional<StringRef> skipTypeSuffix(StringRef typeName) { if (typeName.empty()) return None; auto lastWord = camel_case::getLastWord(typeName); // "Type" suffix. if (lastWord == "Type" && typeName.size() > 4) { return typeName.drop_back(4); } // "Ref" suffix. if (lastWord == "Ref" && typeName.size() > 3) { return typeName.drop_back(3); } // "Mask" suffix. if (lastWord == "Mask" && typeName.size() > 4) { return typeName.drop_back(4); } // \d+D for dimensionality. if (typeName.back() == 'D' && typeName.size() > 1) { unsigned firstDigit = typeName.size() - 1; while (firstDigit > 0) { if (!isdigit(typeName[firstDigit-1])) break; --firstDigit; } if (firstDigit < typeName.size()-1) { return typeName.substr(0, firstDigit); } } // _t. if (typeName.size() > 2 && typeName.endswith("_t")) { return typeName.drop_back(2); } return None; }
static Expected<std::chrono::seconds> parseDuration(StringRef Duration) { if (Duration.empty()) return make_error<StringError>("Duration must not be empty", inconvertibleErrorCode()); StringRef NumStr = Duration.slice(0, Duration.size()-1); uint64_t Num; if (NumStr.getAsInteger(0, Num)) return make_error<StringError>("'" + NumStr + "' not an integer", inconvertibleErrorCode()); switch (Duration.back()) { case 's': return std::chrono::seconds(Num); case 'm': return std::chrono::minutes(Num); case 'h': return std::chrono::hours(Num); default: return make_error<StringError>("'" + Duration + "' must end with one of 's', 'm' or 'h'", inconvertibleErrorCode()); } }
ParsedDeclName swift::parseDeclName(StringRef name) { if (name.empty()) return ParsedDeclName(); // Local function to handle the parsing of the base name + context. // // Returns true if an error occurred, without recording the base name. ParsedDeclName result; auto parseBaseName = [&](StringRef text) -> bool { // Split the text into context name and base name. StringRef contextName, baseName; std::tie(contextName, baseName) = text.rsplit('.'); if (baseName.empty()) { baseName = contextName; contextName = StringRef(); } else if (contextName.empty()) { return true; } auto isValidIdentifier = [](StringRef text) -> bool { return Lexer::isIdentifier(text) && text != "_"; }; // Make sure we have an identifier for the base name. if (!isValidIdentifier(baseName)) return true; // If we have a context, make sure it is an identifier, or a series of // dot-separated identifiers. // FIXME: What about generic parameters? if (!contextName.empty()) { StringRef first; StringRef rest = contextName; do { std::tie(first, rest) = rest.split('.'); if (!isValidIdentifier(first)) return true; } while (!rest.empty()); } // Record the results. result.ContextName = contextName; result.BaseName = baseName; return false; }; // If this is not a function name, just parse the base name and // we're done. if (name.back() != ')') { if (Lexer::isOperator(name)) result.BaseName = name; else if (parseBaseName(name)) return ParsedDeclName(); return result; } // We have a function name. result.IsFunctionName = true; // Split the base name from the parameters. StringRef baseName, parameters; std::tie(baseName, parameters) = name.split('('); if (parameters.empty()) return ParsedDeclName(); // If the base name is prefixed by "getter:" or "setter:", it's an // accessor. if (baseName.startswith("getter:")) { result.IsGetter = true; result.IsFunctionName = false; baseName = baseName.substr(7); } else if (baseName.startswith("setter:")) { result.IsSetter = true; result.IsFunctionName = false; baseName = baseName.substr(7); } // Parse the base name. if (parseBaseName(baseName)) return ParsedDeclName(); parameters = parameters.drop_back(); // ')' if (parameters.empty()) return result; if (parameters.back() != ':') return ParsedDeclName(); bool isMember = !result.ContextName.empty(); do { StringRef NextParam; std::tie(NextParam, parameters) = parameters.split(':'); if (!Lexer::isIdentifier(NextParam)) return ParsedDeclName(); if (NextParam == "_") { result.ArgumentLabels.push_back(""); } else if (isMember && NextParam == "self") { // For a member, "self" indicates the self parameter. There can // only be one such parameter. if (result.SelfIndex) return ParsedDeclName(); result.SelfIndex = result.ArgumentLabels.size(); } else { result.ArgumentLabels.push_back(NextParam); } } while (!parameters.empty()); // Drop the argument labels for a property accessor; they aren't used. if (result.isPropertyAccessor()) result.ArgumentLabels.clear(); return result; }
static bool MacroBodyEndsInBackslash(StringRef MacroBody) { while (!MacroBody.empty() && isWhitespace(MacroBody.back())) MacroBody = MacroBody.drop_back(); return !MacroBody.empty() && MacroBody.back() == '\\'; }
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) { PatternLoc = SMLoc::getFromPointer(PatternStr.data()); // Ignore trailing whitespace. while (!PatternStr.empty() && (PatternStr.back() == ' ' || PatternStr.back() == '\t')) PatternStr = PatternStr.substr(0, PatternStr.size()-1); // Check that there is something on the line. if (PatternStr.empty()) { SM.PrintMessage(PatternLoc, "found empty check string with prefix '" + CheckPrefix+":'", "error"); return true; } // Check to see if this is a fixed string, or if it has regex pieces. if (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && PatternStr.find("[[") == StringRef::npos)) { FixedStr = PatternStr; return false; } // Paren value #0 is for the fully matched string. Any new parenthesized // values add from their. unsigned CurParen = 1; // Otherwise, there is at least one regex piece. Build up the regex pattern // by escaping scary characters in fixed strings, building up one big regex. while (!PatternStr.empty()) { // RegEx matches. if (PatternStr.size() >= 2 && PatternStr[0] == '{' && PatternStr[1] == '{') { // Otherwise, this is the start of a regex match. Scan for the }}. size_t End = PatternStr.find("}}"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), "found start of regex string with no end '}}'", "error"); return true; } if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) return true; PatternStr = PatternStr.substr(End+2); continue; } // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* // (or some other regex) and assigns it to the FileCheck variable 'foo'. The // second form is [[foo]] which is a reference to foo. The variable name // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject // it. This is to catch some common errors. if (PatternStr.size() >= 2 && PatternStr[0] == '[' && PatternStr[1] == '[') { // Verify that it is terminated properly. size_t End = PatternStr.find("]]"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), "invalid named regex reference, no ]] found", "error"); return true; } StringRef MatchStr = PatternStr.substr(2, End-2); PatternStr = PatternStr.substr(End+2); // Get the regex name (e.g. "foo"). size_t NameEnd = MatchStr.find(':'); StringRef Name = MatchStr.substr(0, NameEnd); if (Name.empty()) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), "invalid name in named regex: empty name", "error"); return true; } // Verify that the name is well formed. for (unsigned i = 0, e = Name.size(); i != e; ++i) if (Name[i] != '_' && (Name[i] < 'a' || Name[i] > 'z') && (Name[i] < 'A' || Name[i] > 'Z') && (Name[i] < '0' || Name[i] > '9')) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), "invalid name in named regex", "error"); return true; } // Name can't start with a digit. if (isdigit(Name[0])) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), "invalid name in named regex", "error"); return true; } // Handle [[foo]]. if (NameEnd == StringRef::npos) { VariableUses.push_back(std::make_pair(Name, RegExStr.size())); continue; } // Handle [[foo:.*]]. VariableDefs.push_back(std::make_pair(Name, CurParen)); RegExStr += '('; ++CurParen; if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) return true; RegExStr += ')'; } // Handle fixed string matches. // Find the end, which is the start of the next regex. size_t FixedMatchEnd = PatternStr.find("{{"); FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); PatternStr = PatternStr.substr(FixedMatchEnd); continue; } return false; }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode) const { #ifndef ANDROID_TARGET_BUILD assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer is actually a .s file, just emit the blob textually. // This is useful in case the asm parser doesn't handle something but the // system assembler does. if (OutStreamer.hasRawTextSupport()) { OutStreamer.EmitRawText(Str); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { // If the source manager has an issue, we arrange for SrcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(SrcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } MemoryBuffer *Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); // FIXME: It would be nice if we can avoid createing a new instance of // MCSubtargetInfo here given TargetSubtargetInfo is available. However, // we have to watch out for asm directives which can change subtarget // state. e.g. .code 16, .code 32. OwningPtr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); OwningPtr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(*STI, *Parser)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setTargetParser(*TAP.get()); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); #endif // ANDROID_TARGET_BUILD }
void COFFDumper::printCodeViewSection(const SectionRef &Section) { StringRef Data; error(Section.getContents(Data)); SmallVector<StringRef, 10> FunctionNames; StringMap<StringRef> FunctionLineTables; ListScope D(W, "CodeViewDebugInfo"); { // FIXME: Add more offset correctness checks. DataExtractor DE(Data, true, 4); uint32_t Offset = 0, Magic = DE.getU32(&Offset); W.printHex("Magic", Magic); if (Magic != COFF::DEBUG_SECTION_MAGIC) { error(object_error::parse_failed); return; } bool Finished = false; while (DE.isValidOffset(Offset) && !Finished) { // The section consists of a number of subsection in the following format: // |Type|PayloadSize|Payload...| uint32_t SubSectionType = DE.getU32(&Offset), PayloadSize = DE.getU32(&Offset); ListScope S(W, "Subsection"); W.printHex("Type", SubSectionType); W.printHex("PayloadSize", PayloadSize); if (PayloadSize > Data.size() - Offset) { error(object_error::parse_failed); return; } StringRef Contents = Data.substr(Offset, PayloadSize); if (opts::CodeViewSubsectionBytes) { // Print the raw contents to simplify debugging if anything goes wrong // afterwards. W.printBinaryBlock("Contents", Contents); } switch (SubSectionType) { case COFF::DEBUG_SYMBOL_SUBSECTION: printCodeViewSymbolsSubsection(Contents, Section, Offset); break; case COFF::DEBUG_LINE_TABLE_SUBSECTION: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the // pointers for deferred processing. if (PayloadSize < 12) { // There should be at least three words to store two function // relocations and size of the code. error(object_error::parse_failed); return; } StringRef LinkageName; error(resolveSymbolName(Obj->getCOFFSection(Section), Offset, LinkageName)); W.printString("LinkageName", LinkageName); if (FunctionLineTables.count(LinkageName) != 0) { // Saw debug info for this function already? error(object_error::parse_failed); return; } FunctionLineTables[LinkageName] = Contents; FunctionNames.push_back(LinkageName); break; } case COFF::DEBUG_STRING_TABLE_SUBSECTION: if (PayloadSize == 0 || CVStringTable.data() != nullptr || Contents.back() != '\0') { // Empty or duplicate or non-null-terminated subsection. error(object_error::parse_failed); return; } CVStringTable = Contents; break; case COFF::DEBUG_INDEX_SUBSECTION: // Holds the translation table from file indices // to offsets in the string table. if (PayloadSize == 0 || CVFileIndexToStringOffsetTable.data() != nullptr) { // Empty or duplicate subsection. error(object_error::parse_failed); return; } CVFileIndexToStringOffsetTable = Contents; break; } Offset += PayloadSize; // Align the reading pointer by 4. Offset += (-Offset) % 4; } } // Dump the line tables now that we've read all the subsections and know all // the required information. for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) { StringRef Name = FunctionNames[I]; ListScope S(W, "FunctionLineTable"); W.printString("LinkageName", Name); DataExtractor DE(FunctionLineTables[Name], true, 4); uint32_t Offset = 6; // Skip relocations. uint16_t Flags = DE.getU16(&Offset); W.printHex("Flags", Flags); bool HasColumnInformation = Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS; uint32_t FunctionSize = DE.getU32(&Offset); W.printHex("CodeSize", FunctionSize); while (DE.isValidOffset(Offset)) { // For each range of lines with the same filename, we have a segment // in the line table. The filename string is accessed using double // indirection to the string table subsection using the index subsection. uint32_t OffsetInIndex = DE.getU32(&Offset), SegmentLength = DE.getU32(&Offset), FullSegmentSize = DE.getU32(&Offset); if (FullSegmentSize != 12 + 8 * SegmentLength + (HasColumnInformation ? 4 * SegmentLength : 0)) { error(object_error::parse_failed); return; } uint32_t FilenameOffset; { DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4); uint32_t OffsetInSDE = OffsetInIndex; if (!SDE.isValidOffset(OffsetInSDE)) { error(object_error::parse_failed); return; } FilenameOffset = SDE.getU32(&OffsetInSDE); } if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() || CVStringTable.data()[FilenameOffset - 1] != '\0') { // Each string in an F3 subsection should be preceded by a null // character. error(object_error::parse_failed); return; } StringRef Filename(CVStringTable.data() + FilenameOffset); ListScope S(W, "FilenameSegment"); W.printString("Filename", Filename); for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset); ++J) { // Then go the (PC, LineNumber) pairs. The line number is stored in the // least significant 31 bits of the respective word in the table. uint32_t PC = DE.getU32(&Offset), LineNumber = DE.getU32(&Offset) & 0x7fffffff; if (PC >= FunctionSize) { error(object_error::parse_failed); return; } char Buffer[32]; format("+0x%X", PC).snprint(Buffer, 32); W.printNumber(Buffer, LineNumber); } if (HasColumnInformation) { for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset); ++J) { uint16_t ColStart = DE.getU16(&Offset); W.printNumber("ColStart", ColStart); uint16_t ColEnd = DE.getU16(&Offset); W.printNumber("ColEnd", ColEnd); } } } } }
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, unsigned LineNumber) { this->LineNumber = LineNumber; PatternLoc = SMLoc::getFromPointer(PatternStr.data()); // Ignore trailing whitespace. while (!PatternStr.empty() && (PatternStr.back() == ' ' || PatternStr.back() == '\t')) PatternStr = PatternStr.substr(0, PatternStr.size()-1); // Check that there is something on the line. if (PatternStr.empty()) { SM.PrintMessage(PatternLoc, SourceMgr::DK_Error, "found empty check string with prefix '" + CheckPrefix+":'"); return true; } // Check to see if this is a fixed string, or if it has regex pieces. if (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && PatternStr.find("[[") == StringRef::npos)) { FixedStr = PatternStr; return false; } // Paren value #0 is for the fully matched string. Any new parenthesized // values add from there. unsigned CurParen = 1; // Otherwise, there is at least one regex piece. Build up the regex pattern // by escaping scary characters in fixed strings, building up one big regex. while (!PatternStr.empty()) { // RegEx matches. if (PatternStr.startswith("{{")) { // This is the start of a regex match. Scan for the }}. size_t End = PatternStr.find("}}"); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), SourceMgr::DK_Error, "found start of regex string with no end '}}'"); return true; } // Enclose {{}} patterns in parens just like [[]] even though we're not // capturing the result for any purpose. This is required in case the // expression contains an alternation like: CHECK: abc{{x|z}}def. We // want this to turn into: "abc(x|z)def" not "abcx|zdef". RegExStr += '('; ++CurParen; if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM)) return true; RegExStr += ')'; PatternStr = PatternStr.substr(End+2); continue; } // Named RegEx matches. These are of two forms: [[foo:.*]] which matches .* // (or some other regex) and assigns it to the FileCheck variable 'foo'. The // second form is [[foo]] which is a reference to foo. The variable name // itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject // it. This is to catch some common errors. if (PatternStr.startswith("[[")) { // Find the closing bracket pair ending the match. End is going to be an // offset relative to the beginning of the match string. size_t End = FindRegexVarEnd(PatternStr.substr(2)); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), SourceMgr::DK_Error, "invalid named regex reference, no ]] found"); return true; } StringRef MatchStr = PatternStr.substr(2, End); PatternStr = PatternStr.substr(End+4); // Get the regex name (e.g. "foo"). size_t NameEnd = MatchStr.find(':'); StringRef Name = MatchStr.substr(0, NameEnd); if (Name.empty()) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, "invalid name in named regex: empty name"); return true; } // Verify that the name/expression is well formed. FileCheck currently // supports @LINE, @LINE+number, @LINE-number expressions. The check here // is relaxed, more strict check is performed in \c EvaluateExpression. bool IsExpression = false; for (unsigned i = 0, e = Name.size(); i != e; ++i) { if (i == 0 && Name[i] == '@') { if (NameEnd != StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, "invalid name in named regex definition"); return true; } IsExpression = true; continue; } if (Name[i] != '_' && !isalnum(Name[i]) && (!IsExpression || (Name[i] != '+' && Name[i] != '-'))) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i), SourceMgr::DK_Error, "invalid name in named regex"); return true; } } // Name can't start with a digit. if (isdigit(static_cast<unsigned char>(Name[0]))) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, "invalid name in named regex"); return true; } // Handle [[foo]]. if (NameEnd == StringRef::npos) { // Handle variables that were defined earlier on the same line by // emitting a backreference. if (VariableDefs.find(Name) != VariableDefs.end()) { unsigned VarParenNum = VariableDefs[Name]; if (VarParenNum < 1 || VarParenNum > 9) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, "Can't back-reference more than 9 variables"); return true; } AddBackrefToRegEx(VarParenNum); } else { VariableUses.push_back(std::make_pair(Name, RegExStr.size())); } continue; } // Handle [[foo:.*]]. VariableDefs[Name] = CurParen; RegExStr += '('; ++CurParen; if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM)) return true; RegExStr += ')'; } // Handle fixed string matches. // Find the end, which is the start of the next regex. size_t FixedMatchEnd = PatternStr.find("{{"); FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); PatternStr = PatternStr.substr(FixedMatchEnd); } return false; }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MCTargetOptions &MCOptions, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer->isIntegratedAssemblerRequired()) { emitInlineAsmStart(); OutStreamer->EmitRawText(Str); emitInlineAsmEnd(STI, nullptr); return; } unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode); DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); std::unique_ptr<MCAsmParser> Parser(createMCAsmParser( DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); // Do not use assembler-level information for parsing inline assembly. OutStreamer->setUseAssemblerInfoForParsing(false); // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally // because it's not subtarget dependent. std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo()); std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser( STI, *Parser, *MII, MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); // Enable lexing Masm binary and hex integer literals in intel inline // assembly. if (Dialect == InlineAsm::AD_Intel) Parser->getLexer().setLexMasmIntegers(true); emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STI, &TAP->getSTI()); if (Res && !DiagInfo->DiagHandler) report_fatal_error("Error parsing inline asm\n"); }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MCTargetOptions &MCOptions, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer->isIntegratedAssemblerRequired()) { emitInlineAsmStart(); OutStreamer->EmitRawText(Str); emitInlineAsmEnd(STI, nullptr); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } std::unique_ptr<MemoryBuffer> Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI)); // Create a temporary copy of the original STI because the parser may modify // it. For example, when switching between arm and thumb mode. If the target // needs to emit code to return to the original state it can do so in // emitInlineAsmEnd(). MCSubtargetInfo TmpSTI = STI; // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally // because it's not subtarget dependent. std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo()); std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser( TmpSTI, *Parser, *MII, MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); if (MF) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); } emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STI, &TmpSTI); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MCTargetOptions &MCOptions, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer->isIntegratedAssemblerRequired()) { emitInlineAsmStart(); OutStreamer->EmitRawText(Str); emitInlineAsmEnd(STI, nullptr); return; } if (!DiagInfo) { DiagInfo = make_unique<SrcMgrDiagInfo>(); MCContext &Context = MMI->getContext(); Context.setInlineSourceManager(&DiagInfo->SrcMgr); LLVMContext &LLVMCtx = MMI->getModule()->getContext(); if (LLVMCtx.getInlineAsmDiagnosticHandler()) { DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get()); } } SourceMgr &SrcMgr = DiagInfo->SrcMgr; SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); std::unique_ptr<MemoryBuffer> Buffer; // The inline asm source manager will outlive Str, so make a copy of the // string for SourceMgr to own. Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); // Store LocMDNode in DiagInfo, using BufNum as an identifier. if (LocMDNode) { DiagInfo->LocInfos.resize(BufNum); DiagInfo->LocInfos[BufNum-1] = LocMDNode; } std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); // We create a new MCInstrInfo here since we might be at the module level // and not have a MachineFunction to initialize the TargetInstrInfo from and // we only need MCInstrInfo for asm parsing. We create one unconditionally // because it's not subtarget dependent. std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo()); std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser( STI, *Parser, *MII, MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); Parser->setEnablePrintSchedInfo(EnablePrintSchedInfo); if (Dialect == InlineAsm::AD_Intel) // We need this flag to be able to parse numbers like "0bH" Parser->setParsingInlineAsm(true); if (MF) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); } emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STI, &TAP->getSTI()); if (Res && !DiagInfo->DiagHandler) report_fatal_error("Error parsing inline asm\n"); }
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, InlineAsm::AsmDialect Dialect) const { assert(!Str.empty() && "Can't emit empty inline asm block"); // Remember if the buffer is nul terminated or not so we can avoid a copy. bool isNullTerminated = Str.back() == 0; if (isNullTerminated) Str = Str.substr(0, Str.size()-1); // If the output streamer does not have mature MC support or the integrated // assembler has been disabled, just emit the blob textually. // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. const MCAsmInfo *MCAI = TM.getMCAsmInfo(); assert(MCAI && "No MCAsmInfo"); if (!MCAI->useIntegratedAssembler() && !OutStreamer.isIntegratedAssemblerRequired()) { emitInlineAsmStart(TM.getSubtarget<MCSubtargetInfo>()); OutStreamer.EmitRawText(Str); emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), nullptr); return; } SourceMgr SrcMgr; SrcMgrDiagInfo DiagInfo; // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo); HasDiagHandler = true; } std::unique_ptr<MemoryBuffer> Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); // Initialize the parser with a fresh subtarget info. It is better to use a // new STI here because the parser may modify it and we do not want those // modifications to persist after parsing the inlineasm. The modifications // made by the parser will be seen by the code emitters because it passes // the current STI down to the EncodeInstruction() method. std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); // Preserve a copy of the original STI because the parser may modify it. For // example, when switching between arm and thumb mode. If the target needs to // emit code to return to the original state it can do so in // emitInlineAsmEnd(). MCSubtargetInfo STIOrig = *STI; MCTargetOptions MCOptions; if (MF) MCOptions = MF->getTarget().Options.MCOptions; std::unique_ptr<MCTargetAsmParser> TAP( TM.getTarget().createMCAsmParser(*STI, *Parser, *MII, MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); if (MF) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); } emitInlineAsmStart(STIOrig); // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); emitInlineAsmEnd(STIOrig, STI.get()); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); }
/// StripSpaces - This removes leading and trailing spaces from the StringRef. static void StripSpaces(StringRef &Str) { while (!Str.empty() && isspace(Str[0])) Str = Str.substr(1); while (!Str.empty() && isspace(Str.back())) Str = Str.substr(0, Str.size()-1); }