void jl_dump_function_asm(const char *Fptr, size_t Fsize, #ifndef USE_MCJIT std::vector<JITEvent_EmittedFunctionDetails::LineStart> lineinfo, #else const object::ObjectFile *objectfile, #endif formatted_raw_ostream &stream) { // Initialize targets and assembly printers/parsers. // Avoids hard-coded targets - will generally be only host CPU anyway. llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetDisassembler(); // Get the host information std::string TripleName; if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); std::string MCPU = sys::getHostCPUName(); SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(TheTriple); std::string err; const Target* TheTarget = TargetRegistry::lookupTarget(TripleName, err); // Set up required helpers and streamer #ifdef LLVM35 std::unique_ptr<MCStreamer> Streamer; #else OwningPtr<MCStreamer> Streamer; #endif SourceMgr SrcMgr; #ifdef LLVM35 std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #elif defined(LLVM34) llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #else llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); #endif assert(MAI && "Unable to create target asm info!"); #ifdef LLVM35 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); #else llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); #endif assert(MRI && "Unable to create target register info!"); #ifdef LLVM35 std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #else OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #endif #ifdef LLVM34 MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); #else MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); #endif MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default, Ctx); // Set up Subtarget and Disassembler #ifdef LLVM35 std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); std::unique_ptr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx)); #else OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); OwningPtr<MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); #endif if (!DisAsm) { JL_PRINTF(JL_STDERR, "error: no disassembler for target", TripleName.c_str(), "\n"); return; } unsigned OutputAsmVariant = 1; bool ShowEncoding = false; bool ShowInst = false; #ifdef LLVM35 std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCInstrAnalysis> MCIA(TheTarget->createMCInstrAnalysis(MCII.get())); #else OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<MCInstrAnalysis> MCIA(TheTarget->createMCInstrAnalysis(MCII.get())); #endif MCInstPrinter* IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); #ifdef LLVM34 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); #else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); #endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, #ifndef LLVM35 /*useLoc*/ true, /*useCFI*/ true, #endif /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); #ifdef LLVM36 Streamer->InitSections(true); #else Streamer->InitSections(); #endif // Make the MemoryObject wrapper #ifdef LLVM36 ArrayRef<uint8_t> memoryObject(const_cast<uint8_t*>((const uint8_t*)Fptr),Fsize); #else FuncMCView memoryObject(Fptr, Fsize); #endif SymbolTable DisInfo(Ctx, memoryObject); #ifdef USE_MCJIT if (!objectfile) return; #ifdef LLVM36 DIContext *di_ctx = DIContext::getDWARFContext(*objectfile); #else DIContext *di_ctx = DIContext::getDWARFContext(const_cast<object::ObjectFile*>(objectfile)); #endif if (di_ctx == NULL) return; DILineInfoTable lineinfo = di_ctx->getLineInfoForAddressRange((size_t)Fptr, Fsize); #else typedef std::vector<JITEvent_EmittedFunctionDetails::LineStart> LInfoVec; #endif // Take two passes: In the first pass we record all branch labels, // in the second we actually perform the output for (int pass = 0; pass < 2; ++ pass) { DisInfo.setPass(pass); if (pass != 0) { // Switch to symbolic disassembly. We cannot do this // before the first pass, because this changes branch // targets from immediate values (constants) to // expressions, which are not handled correctly by // MCIA->evaluateBranch. (It should be possible to rewrite // this routine to handle this case correctly as well.) // Could add OpInfoLookup here #ifdef LLVM35 DisAsm->setSymbolizer(std::unique_ptr<MCSymbolizer>(new MCExternalSymbolizer( Ctx, std::unique_ptr<MCRelocationInfo>(new MCRelocationInfo(Ctx)), OpInfoLookup, SymbolLookup, &DisInfo))); #else DisAsm->setupForSymbolicDisassembly( OpInfoLookup, SymbolLookup, &DisInfo, &Ctx); #endif } uint64_t nextLineAddr = -1; #ifdef USE_MCJIT // Set up the line info DILineInfoTable::iterator lineIter = lineinfo.begin(); DILineInfoTable::iterator lineEnd = lineinfo.end(); if (lineIter != lineEnd) { nextLineAddr = lineIter->first; if (pass != 0) { #ifdef LLVM35 stream << "Filename: " << lineIter->second.FileName << "\n"; #else stream << "Filename: " << lineIter->second.getFileName() << "\n"; #endif } } #else // Set up the line info LInfoVec::iterator lineIter = lineinfo.begin(); LInfoVec::iterator lineEnd = lineinfo.end(); if (lineIter != lineEnd) { nextLineAddr = (*lineIter).Address; DISubprogram debugscope = DISubprogram((*lineIter).Loc.getScope(jl_LLVMContext)); if (pass != 0) { stream << "Filename: " << debugscope.getFilename() << "\n"; stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; } } #endif uint64_t Index = 0; uint64_t absAddr = 0; uint64_t insSize = 0; // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < Fsize; Index += insSize, absAddr += insSize) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { #ifdef USE_MCJIT #ifdef LLVM35 if (pass != 0) stream << "Source line: " << lineIter->second.Line << "\n"; #else if (pass != 0) stream << "Source line: " << lineIter->second.getLine() << "\n"; #endif nextLineAddr = (++lineIter)->first; #else if (pass != 0) stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; nextLineAddr = (*++lineIter).Address; #endif } if (pass != 0) { // Uncomment this to output addresses for all instructions // stream << Index << ": "; const char *symbolName = DisInfo.lookupSymbol(Index); if (symbolName) stream << symbolName << ":"; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, insSize, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: if (pass != 0) SrcMgr.PrintMessage(SMLoc::getFromPointer(Fptr + Index), SourceMgr::DK_Warning, "invalid instruction encoding"); if (insSize == 0) insSize = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: if (pass != 0) SrcMgr.PrintMessage(SMLoc::getFromPointer(Fptr + Index), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: if (pass == 0) { // Pass 0: Record all branch targets if (MCIA->isBranch(Inst)) { uint64_t addr; #ifdef LLVM35 if (MCIA->evaluateBranch(Inst, Index, insSize, addr)) #else if ((addr = MCIA->evaluateBranch(Inst, Index, insSize)) != (uint64_t)-1) #endif DisInfo.insertAddress(addr); } } else { // Pass 1: Output instruction #ifdef LLVM35 Streamer->EmitInstruction(Inst, *STI); #else Streamer->EmitInstruction(Inst); #endif } break; } } if (pass == 0) DisInfo.createSymbols(); } }
int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); SourceMgr SM; // Read the expected strings from the check file. std::vector<CheckString> CheckStrings; if (ReadCheckFile(SM, CheckStrings)) return 2; // Open the file to check and add it to SourceMgr. OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { errs() << "Could not open input file '" << InputFilename << "': " << ec.message() << '\n'; return 2; } MemoryBuffer *F = File.take(); if (F->getBufferSize() == 0) { errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; return 2; } // Remove duplicate spaces in the input file if requested. // Remove DOS style line endings. F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); /// VariableTable - This holds all the current filecheck variables. StringMap<StringRef> VariableTable; // Check that we have all of the expected strings, in order, in the input // file. StringRef Buffer = F->getBuffer(); const char *LastMatch = Buffer.data(); for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) { const CheckString &CheckStr = CheckStrings[StrNo]; StringRef SearchFrom = Buffer; // Find StrNo in the file. size_t MatchLen = 0; size_t MatchPos = CheckStr.Pat.Match(Buffer, MatchLen, VariableTable); Buffer = Buffer.substr(MatchPos); // If we didn't find a match, reject the input. if (MatchPos == StringRef::npos) { PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable); return 1; } StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch); // If this check is a "CHECK-NEXT", verify that the previous match was on // the previous line (i.e. that there is one newline between them). if (CheckStr.IsCheckNext) { // Count the number of newlines between the previous match and this one. assert(LastMatch != F->getBufferStart() && "CHECK-NEXT can't be the first check in a file"); unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion); if (NumNewLines == 0) { SM.PrintMessage(CheckStr.Loc, SourceMgr::DK_Error, CheckPrefix+"-NEXT: is on the same line as previous match"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, "'next' match was here"); SM.PrintMessage(SMLoc::getFromPointer(LastMatch), SourceMgr::DK_Note, "previous match was here"); return 1; } if (NumNewLines != 1) { SM.PrintMessage(CheckStr.Loc, SourceMgr::DK_Error, CheckPrefix+ "-NEXT: is not on the line after the previous match"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, "'next' match was here"); SM.PrintMessage(SMLoc::getFromPointer(LastMatch), SourceMgr::DK_Note, "previous match was here"); return 1; } } // If this match had "not strings", verify that they don't exist in the // skipped region. for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size(); ChunkNo != e; ++ChunkNo) { size_t MatchLen = 0; size_t Pos = CheckStr.NotStrings[ChunkNo].second.Match(SkippedRegion, MatchLen, VariableTable); if (Pos == StringRef::npos) continue; SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos), SourceMgr::DK_Error, CheckPrefix+"-NOT: string occurred!"); SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first, SourceMgr::DK_Note, CheckPrefix+"-NOT: pattern specified here"); return 1; } // Otherwise, everything is good. Step over the matched text and remember // the position after the match as the end of the last match. Buffer = Buffer.substr(MatchLen); LastMatch = Buffer.data(); } return 0; }
void llvm::PrintError(SMLoc ErrorLoc, const Twine &Msg) { SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); }
void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, const StringMap<StringRef> &VariableTable) const{ // If this was a regular expression using variables, print the current // variable values. if (!VariableUses.empty()) { for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) { SmallString<256> Msg; raw_svector_ostream OS(Msg); StringRef Var = VariableUses[i].first; if (Var[0] == '@') { std::string Value; if (EvaluateExpression(Var, Value)) { OS << "with expression \""; OS.write_escaped(Var) << "\" equal to \""; OS.write_escaped(Value) << "\""; } else { OS << "uses incorrect expression \""; OS.write_escaped(Var) << "\""; } } else { StringMap<StringRef>::const_iterator it = VariableTable.find(Var); // Check for undefined variable references. if (it == VariableTable.end()) { OS << "uses undefined variable \""; OS.write_escaped(Var) << "\""; } else { OS << "with variable \""; OS.write_escaped(Var) << "\" equal to \""; OS.write_escaped(it->second) << "\""; } } SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, OS.str()); } } // Attempt to find the closest/best fuzzy match. Usually an error happens // because some string in the output didn't exactly match. In these cases, we // would like to show the user a best guess at what "should have" matched, to // save them having to actually check the input manually. size_t NumLinesForward = 0; size_t Best = StringRef::npos; double BestQuality = 0; // Use an arbitrary 4k limit on how far we will search. for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { if (Buffer[i] == '\n') ++NumLinesForward; // Patterns have leading whitespace stripped, so skip whitespace when // looking for something which looks like a pattern. if (Buffer[i] == ' ' || Buffer[i] == '\t') continue; // Compute the "quality" of this match as an arbitrary combination of the // match distance and the number of lines skipped to get to this match. unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable); double Quality = Distance + (NumLinesForward / 100.); if (Quality < BestQuality || Best == StringRef::npos) { Best = i; BestQuality = Quality; } } // Print the "possible intended match here" line if we found something // reasonable and not equal to what we showed in the "scanning from here" // line. if (Best && Best != StringRef::npos && BestQuality < 50) { SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Best), SourceMgr::DK_Note, "possible intended match here"); // FIXME: If we wanted to be really friendly we would show why the match // failed, as it can be hard to spot simple one character differences. } }
/// ReadCheckFile - Read the check file, which specifies the sequence of /// expected strings. The strings are added to the CheckStrings vector. /// Returns true in case of an error, false otherwise. static bool ReadCheckFile(SourceMgr &SM, std::vector<CheckString> &CheckStrings) { OwningPtr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) { errs() << "Could not open check file '" << CheckFilename << "': " << ec.message() << '\n'; return true; } MemoryBuffer *F = File.take(); // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. Remove DOS style line endings. F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); std::vector<std::pair<SMLoc, Pattern> > NotMatches; // LineNumber keeps track of the line on which CheckPrefix instances are // found. unsigned LineNumber = 1; while (1) { // See if Prefix occurs in the memory buffer. size_t PrefixLoc = Buffer.find(CheckPrefix); // If we didn't find a match, we're done. if (PrefixLoc == StringRef::npos) break; LineNumber += Buffer.substr(0, PrefixLoc).count('\n'); Buffer = Buffer.substr(PrefixLoc); const char *CheckPrefixStart = Buffer.data(); // When we find a check prefix, keep track of whether we find CHECK: or // CHECK-NEXT: bool IsCheckNext = false, IsCheckNot = false; // Verify that the : is present after the prefix. if (Buffer[CheckPrefix.size()] == ':') { Buffer = Buffer.substr(CheckPrefix.size()+1); } else if (Buffer.size() > CheckPrefix.size()+6 && memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+6); IsCheckNext = true; } else if (Buffer.size() > CheckPrefix.size()+5 && memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+5); IsCheckNot = true; } else { Buffer = Buffer.substr(1); continue; } // Okay, we found the prefix, yay. Remember the rest of the line, but // ignore leading and trailing whitespace. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); // Scan ahead to the end of line. size_t EOL = Buffer.find_first_of("\n\r"); // Remember the location of the start of the pattern, for diagnostics. SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); // Parse the pattern. Pattern P; if (P.ParsePattern(Buffer.substr(0, EOL), SM, LineNumber)) return true; Buffer = Buffer.substr(EOL); // Verify that CHECK-NEXT lines have at least one CHECK line before them. if (IsCheckNext && CheckStrings.empty()) { SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), SourceMgr::DK_Error, "found '"+CheckPrefix+"-NEXT:' without previous '"+ CheckPrefix+ ": line"); return true; } // Handle CHECK-NOT. if (IsCheckNot) { NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()), P)); continue; } // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, PatternLoc, IsCheckNext)); std::swap(NotMatches, CheckStrings.back().NotStrings); } // Add an EOF pattern for any trailing CHECK-NOTs. if (!NotMatches.empty()) { CheckStrings.push_back(CheckString(Pattern(true), SMLoc::getFromPointer(Buffer.data()), false)); std::swap(NotMatches, CheckStrings.back().NotStrings); } if (CheckStrings.empty()) { errs() << "error: no check strings found with prefix '" << CheckPrefix << ":'\n"; return true; } return false; }
void jl_dump_function_asm(void* Fptr, size_t Fsize, std::vector<JITEvent_EmittedFunctionDetails::LineStart> lineinfo, formatted_raw_ostream &stream) { // Initialize targets and assembly printers/parsers. // Avoids hard-coded targets - will generally be only host CPU anyway. llvm::InitializeNativeTargetAsmParser(); llvm::InitializeNativeTargetDisassembler(); // Get the host information std::string TripleName; if (TripleName.empty()) TripleName = sys::getDefaultTargetTriple(); Triple TheTriple(Triple::normalize(TripleName)); std::string MCPU = sys::getHostCPUName(); SubtargetFeatures Features; Features.getDefaultSubtargetFeatures(TheTriple); std::string err; const Target* TheTarget = TargetRegistry::lookupTarget(TripleName, err); // Set up required helpers and streamer OwningPtr<MCStreamer> Streamer; SourceMgr SrcMgr; #ifdef LLVM34 llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*TheTarget->createMCRegInfo(TripleName),TripleName)); #else llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName)); #endif assert(MAI && "Unable to create target asm info!"); llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); #ifdef LLVM34 MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); #else MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); #endif MOFI->InitMCObjectFileInfo(TripleName, Reloc::Default, CodeModel::Default, Ctx); // Set up Subtarget and Disassembler OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString())); #ifdef LLVM35 OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI, Ctx)); #else OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI)); #endif if (!DisAsm) { JL_PRINTF(JL_STDERR, "error: no disassembler for target", TripleName.c_str(), "\n"); return; } unsigned OutputAsmVariant = 1; bool ShowEncoding = false; bool ShowInst = false; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); MCInstPrinter* IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); #ifdef LLVM34 MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); #else MAB = TheTarget->createMCAsmBackend(TripleName, MCPU); #endif } Streamer.reset(TheTarget->createAsmStreamer(Ctx, stream, /*asmverbose*/true, #ifndef LLVM35 /*useLoc*/ true, /*useCFI*/ true, #endif /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); Streamer->InitSections(); // Make the MemoryObject wrapper FuncMCView memoryObject(Fptr, Fsize); uint64_t Size; uint64_t Index; uint64_t absAddr; // Set up the line info typedef std::vector<JITEvent_EmittedFunctionDetails::LineStart> LInfoVec; LInfoVec::iterator lineIter = lineinfo.begin(); lineIter = lineinfo.begin(); uint64_t nextLineAddr = -1; DISubprogram debugscope; if (lineIter != lineinfo.end()) { nextLineAddr = (*lineIter).Address; debugscope = DISubprogram((*lineIter).Loc.getScope(jl_LLVMContext)); stream << "Filename: " << debugscope.getFilename().data() << "\n"; stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; } // Do the disassembly for (Index = 0, absAddr = (uint64_t)Fptr; Index < memoryObject.getExtent(); Index += Size, absAddr += Size) { if (nextLineAddr != (uint64_t)-1 && absAddr == nextLineAddr) { stream << "Source line: " << (*lineIter).Loc.getLine() << "\n"; nextLineAddr = (*++lineIter).Address; } MCInst Inst; MCDisassembler::DecodeStatus S; S = DisAsm->getInstruction(Inst, Size, memoryObject, Index, /*REMOVE*/ nulls(), nulls()); switch (S) { case MCDisassembler::Fail: SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "invalid instruction encoding"); if (Size == 0) Size = 1; // skip illegible bytes break; case MCDisassembler::SoftFail: SrcMgr.PrintMessage(SMLoc::getFromPointer(memoryObject[Index]), SourceMgr::DK_Warning, "potentially undefined instruction encoding"); // Fall through case MCDisassembler::Success: #ifdef LLVM35 Streamer->EmitInstruction(Inst, *STI); #else Streamer->EmitInstruction(Inst); #endif break; } } }
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; }
/// ReadCheckFile - Read the check file, which specifies the sequence of /// expected strings. The strings are added to the CheckStrings vector. static bool ReadCheckFile(SourceMgr &SM, std::vector<CheckString> &CheckStrings) { // Open the check file, and tell SourceMgr about it. std::string ErrorStr; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr); if (F == 0) { errs() << "Could not open check file '" << CheckFilename << "': " << ErrorStr << '\n'; return true; } // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. if (!NoCanonicalizeWhiteSpace) F = CanonicalizeInputFile(F); SM.AddNewSourceBuffer(F, SMLoc()); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); std::vector<std::pair<SMLoc, Pattern> > NotMatches; while (1) { // See if Prefix occurs in the memory buffer. Buffer = Buffer.substr(Buffer.find(CheckPrefix)); // If we didn't find a match, we're done. if (Buffer.empty()) break; const char *CheckPrefixStart = Buffer.data(); // When we find a check prefix, keep track of whether we find CHECK: or // CHECK-NEXT: bool IsCheckNext = false, IsCheckNot = false; // Verify that the : is present after the prefix. if (Buffer[CheckPrefix.size()] == ':') { Buffer = Buffer.substr(CheckPrefix.size()+1); } else if (Buffer.size() > CheckPrefix.size()+6 && memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+7); IsCheckNext = true; } else if (Buffer.size() > CheckPrefix.size()+5 && memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) { Buffer = Buffer.substr(CheckPrefix.size()+6); IsCheckNot = true; } else { Buffer = Buffer.substr(1); continue; } // Okay, we found the prefix, yay. Remember the rest of the line, but // ignore leading and trailing whitespace. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); // Scan ahead to the end of line. size_t EOL = Buffer.find_first_of("\n\r"); // Remember the location of the start of the pattern, for diagnostics. SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); // Parse the pattern. Pattern P; if (P.ParsePattern(Buffer.substr(0, EOL), SM)) return true; Buffer = Buffer.substr(EOL); // Verify that CHECK-NEXT lines have at least one CHECK line before them. if (IsCheckNext && CheckStrings.empty()) { SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart), "found '"+CheckPrefix+"-NEXT:' without previous '"+ CheckPrefix+ ": line", "error"); return true; } // Handle CHECK-NOT. if (IsCheckNot) { NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()), P)); continue; } // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, PatternLoc, IsCheckNext)); std::swap(NotMatches, CheckStrings.back().NotStrings); } if (CheckStrings.empty()) { errs() << "error: no check strings found with prefix '" << CheckPrefix << ":'\n"; return true; } if (!NotMatches.empty()) { errs() << "error: '" << CheckPrefix << "-NOT:' not supported after last check line.\n"; return true; } return false; }
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, raw_ostream &OS) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(SrcMgr.getMainFileID())->getBuffer()); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { const AsmToken &Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: OS << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: OS << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: OS << "real: " << Lexer.getTok().getString(); break; case AsmToken::String: OS << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: OS << "Amp"; break; case AsmToken::AmpAmp: OS << "AmpAmp"; break; case AsmToken::At: OS << "At"; break; case AsmToken::Caret: OS << "Caret"; break; case AsmToken::Colon: OS << "Colon"; break; case AsmToken::Comma: OS << "Comma"; break; case AsmToken::Dollar: OS << "Dollar"; break; case AsmToken::Dot: OS << "Dot"; break; case AsmToken::EndOfStatement: OS << "EndOfStatement"; break; case AsmToken::Eof: OS << "Eof"; break; case AsmToken::Equal: OS << "Equal"; break; case AsmToken::EqualEqual: OS << "EqualEqual"; break; case AsmToken::Exclaim: OS << "Exclaim"; break; case AsmToken::ExclaimEqual: OS << "ExclaimEqual"; break; case AsmToken::Greater: OS << "Greater"; break; case AsmToken::GreaterEqual: OS << "GreaterEqual"; break; case AsmToken::GreaterGreater: OS << "GreaterGreater"; break; case AsmToken::Hash: OS << "Hash"; break; case AsmToken::LBrac: OS << "LBrac"; break; case AsmToken::LCurly: OS << "LCurly"; break; case AsmToken::LParen: OS << "LParen"; break; case AsmToken::Less: OS << "Less"; break; case AsmToken::LessEqual: OS << "LessEqual"; break; case AsmToken::LessGreater: OS << "LessGreater"; break; case AsmToken::LessLess: OS << "LessLess"; break; case AsmToken::Minus: OS << "Minus"; break; case AsmToken::Percent: OS << "Percent"; break; case AsmToken::Pipe: OS << "Pipe"; break; case AsmToken::PipePipe: OS << "PipePipe"; break; case AsmToken::Plus: OS << "Plus"; break; case AsmToken::RBrac: OS << "RBrac"; break; case AsmToken::RCurly: OS << "RCurly"; break; case AsmToken::RParen: OS << "RParen"; break; case AsmToken::Slash: OS << "Slash"; break; case AsmToken::Star: OS << "Star"; break; case AsmToken::Tilde: OS << "Tilde"; break; case AsmToken::PercentCall16: OS << "PercentCall16"; break; case AsmToken::PercentCall_Hi: OS << "PercentCall_Hi"; break; case AsmToken::PercentCall_Lo: OS << "PercentCall_Lo"; break; case AsmToken::PercentDtprel_Hi: OS << "PercentDtprel_Hi"; break; case AsmToken::PercentDtprel_Lo: OS << "PercentDtprel_Lo"; break; case AsmToken::PercentGot: OS << "PercentGot"; break; case AsmToken::PercentGot_Disp: OS << "PercentGot_Disp"; break; case AsmToken::PercentGot_Hi: OS << "PercentGot_Hi"; break; case AsmToken::PercentGot_Lo: OS << "PercentGot_Lo"; break; case AsmToken::PercentGot_Ofst: OS << "PercentGot_Ofst"; break; case AsmToken::PercentGot_Page: OS << "PercentGot_Page"; break; case AsmToken::PercentGottprel: OS << "PercentGottprel"; break; case AsmToken::PercentGp_Rel: OS << "PercentGp_Rel"; break; case AsmToken::PercentHi: OS << "PercentHi"; break; case AsmToken::PercentHigher: OS << "PercentHigher"; break; case AsmToken::PercentHighest: OS << "PercentHighest"; break; case AsmToken::PercentLo: OS << "PercentLo"; break; case AsmToken::PercentNeg: OS << "PercentNeg"; break; case AsmToken::PercentPcrel_Hi: OS << "PercentPcrel_Hi"; break; case AsmToken::PercentPcrel_Lo: OS << "PercentPcrel_Lo"; break; case AsmToken::PercentTlsgd: OS << "PercentTlsgd"; break; case AsmToken::PercentTlsldm: OS << "PercentTlsldm"; break; case AsmToken::PercentTprel_Hi: OS << "PercentTprel_Hi"; break; case AsmToken::PercentTprel_Lo: OS << "PercentTprel_Lo"; break; } // Print the token string. OS << " (\""; OS.write_escaped(Tok.getString()); OS << "\")\n"; } return Error; }
void PrintError(const char *Loc, const Twine &Msg) { SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg); }
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; }
void PrintWarning(const char *Loc, const Twine &Msg) { SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Warning, Msg); }
static void parseMCMarkup(StringRef Filename) { OwningPtr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, BufferPtr)) { errs() << ToolName << ": " << ec.message() << '\n'; return; } MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); StringRef InputSource = Buffer->getBuffer(); MarkupLexer Lex(InputSource); MarkupParser Parser(Lex, SrcMgr); SmallVector<MarkupTag, 4> TagStack; for (int CurChar = Lex.getNextChar(); CurChar != EOF; CurChar = Lex.getNextChar()) { switch (CurChar) { case '<': { // A "<<" is output as a literal '<' and does not start a markup tag. if (Lex.peekNextChar() == '<') { (void)Lex.getNextChar(); break; } // Parse the markup entry. TagStack.push_back(Parser.parseTag()); // Do any special handling for the start of a tag. processStartTag(TagStack.back()); continue; } case '>': { SMLoc Loc = SMLoc::getFromPointer(Lex.getPosition() - 1); // A ">>" is output as a literal '>' and does not end a markup tag. if (Lex.peekNextChar() == '>') { (void)Lex.getNextChar(); break; } // Close out the innermost tag. if (TagStack.empty()) Parser.FatalError(Loc, "'>' without matching '<'"); // Do any special handling for the end of a tag. processEndTag(TagStack.back()); TagStack.pop_back(); continue; } default: break; } // For anything else, just echo the character back out. if (!DumpTags && CurChar != EOF) outs() << (char)CurChar; } // If there are any unterminated markup tags, issue diagnostics for them. while (!TagStack.empty()) { MarkupTag &Tag = TagStack.back(); SrcMgr.PrintMessage(Tag.getLoc(), SourceMgr::DK_Error, "unterminated markup tag"); TagStack.pop_back(); } }
static int AsLexInput(const char *ProgName) { std::string ErrorMessage; MemoryBuffer *Buffer = MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage); if (Buffer == 0) { errs() << ProgName << ": "; if (ErrorMessage.size()) errs() << ErrorMessage << "\n"; else errs() << "input file didn't read correctly.\n"; return 1; } SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createAsmInfo(TripleName)); assert(MAI && "Unable to create target asm info!"); AsmLexer Lexer(*MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { switch (Lexer.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), "unknown token", "warning"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: outs() << "identifier: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::String: outs() << "string: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Integer: outs() << "int: " << Lexer.getTok().getString() << '\n'; break; case AsmToken::Amp: outs() << "Amp\n"; break; case AsmToken::AmpAmp: outs() << "AmpAmp\n"; break; case AsmToken::Caret: outs() << "Caret\n"; break; case AsmToken::Colon: outs() << "Colon\n"; break; case AsmToken::Comma: outs() << "Comma\n"; break; case AsmToken::Dollar: outs() << "Dollar\n"; break; case AsmToken::EndOfStatement: outs() << "EndOfStatement\n"; break; case AsmToken::Eof: outs() << "Eof\n"; break; case AsmToken::Equal: outs() << "Equal\n"; break; case AsmToken::EqualEqual: outs() << "EqualEqual\n"; break; case AsmToken::Exclaim: outs() << "Exclaim\n"; break; case AsmToken::ExclaimEqual: outs() << "ExclaimEqual\n"; break; case AsmToken::Greater: outs() << "Greater\n"; break; case AsmToken::GreaterEqual: outs() << "GreaterEqual\n"; break; case AsmToken::GreaterGreater: outs() << "GreaterGreater\n"; break; case AsmToken::LParen: outs() << "LParen\n"; break; case AsmToken::Less: outs() << "Less\n"; break; case AsmToken::LessEqual: outs() << "LessEqual\n"; break; case AsmToken::LessGreater: outs() << "LessGreater\n"; break; case AsmToken::LessLess: outs() << "LessLess\n"; break; case AsmToken::Minus: outs() << "Minus\n"; break; case AsmToken::Percent: outs() << "Percent\n"; break; case AsmToken::Pipe: outs() << "Pipe\n"; break; case AsmToken::PipePipe: outs() << "PipePipe\n"; break; case AsmToken::Plus: outs() << "Plus\n"; break; case AsmToken::RParen: outs() << "RParen\n"; break; case AsmToken::Slash: outs() << "Slash\n"; break; case AsmToken::Star: outs() << "Star\n"; break; case AsmToken::Tilde: outs() << "Tilde\n"; break; } } return Error; }
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) { AsmLexer Lexer(MAI); Lexer.setBuffer(SrcMgr.getMemoryBuffer(0)); bool Error = false; while (Lexer.Lex().isNot(AsmToken::Eof)) { AsmToken Tok = Lexer.getTok(); switch (Tok.getKind()) { default: SrcMgr.PrintMessage(Lexer.getLoc(), SourceMgr::DK_Warning, "unknown token"); Error = true; break; case AsmToken::Error: Error = true; // error already printed. break; case AsmToken::Identifier: Out->os() << "identifier: " << Lexer.getTok().getString(); break; case AsmToken::Integer: Out->os() << "int: " << Lexer.getTok().getString(); break; case AsmToken::Real: Out->os() << "real: " << Lexer.getTok().getString(); break; case AsmToken::String: Out->os() << "string: " << Lexer.getTok().getString(); break; case AsmToken::Amp: Out->os() << "Amp"; break; case AsmToken::AmpAmp: Out->os() << "AmpAmp"; break; case AsmToken::At: Out->os() << "At"; break; case AsmToken::Caret: Out->os() << "Caret"; break; case AsmToken::Colon: Out->os() << "Colon"; break; case AsmToken::Comma: Out->os() << "Comma"; break; case AsmToken::Dollar: Out->os() << "Dollar"; break; case AsmToken::Dot: Out->os() << "Dot"; break; case AsmToken::EndOfStatement: Out->os() << "EndOfStatement"; break; case AsmToken::Eof: Out->os() << "Eof"; break; case AsmToken::Equal: Out->os() << "Equal"; break; case AsmToken::EqualEqual: Out->os() << "EqualEqual"; break; case AsmToken::Exclaim: Out->os() << "Exclaim"; break; case AsmToken::ExclaimEqual: Out->os() << "ExclaimEqual"; break; case AsmToken::Greater: Out->os() << "Greater"; break; case AsmToken::GreaterEqual: Out->os() << "GreaterEqual"; break; case AsmToken::GreaterGreater: Out->os() << "GreaterGreater"; break; case AsmToken::Hash: Out->os() << "Hash"; break; case AsmToken::LBrac: Out->os() << "LBrac"; break; case AsmToken::LCurly: Out->os() << "LCurly"; break; case AsmToken::LParen: Out->os() << "LParen"; break; case AsmToken::Less: Out->os() << "Less"; break; case AsmToken::LessEqual: Out->os() << "LessEqual"; break; case AsmToken::LessGreater: Out->os() << "LessGreater"; break; case AsmToken::LessLess: Out->os() << "LessLess"; break; case AsmToken::Minus: Out->os() << "Minus"; break; case AsmToken::Percent: Out->os() << "Percent"; break; case AsmToken::Pipe: Out->os() << "Pipe"; break; case AsmToken::PipePipe: Out->os() << "PipePipe"; break; case AsmToken::Plus: Out->os() << "Plus"; break; case AsmToken::RBrac: Out->os() << "RBrac"; break; case AsmToken::RCurly: Out->os() << "RCurly"; break; case AsmToken::RParen: Out->os() << "RParen"; break; case AsmToken::Slash: Out->os() << "Slash"; break; case AsmToken::Star: Out->os() << "Star"; break; case AsmToken::Tilde: Out->os() << "Tilde"; break; } // Print the token string. Out->os() << " (\""; Out->os().write_escaped(Tok.getString()); Out->os() << "\")\n"; } return Error; }
/// ReadCheckFile - Read the check file, which specifies the sequence of /// expected strings. The strings are added to the CheckStrings vector. /// Returns true in case of an error, false otherwise. static bool ReadCheckFile(SourceMgr &SM, std::vector<CheckString> &CheckStrings) { std::unique_ptr<MemoryBuffer> File; if (std::error_code ec = MemoryBuffer::getFileOrSTDIN(CheckFilename, File)) { errs() << "Could not open check file '" << CheckFilename << "': " << ec.message() << '\n'; return true; } // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. Remove DOS style line endings. MemoryBuffer *F = CanonicalizeInputFile(File.release(), NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); std::vector<Pattern> DagNotMatches; // LineNumber keeps track of the line on which CheckPrefix instances are // found. unsigned LineNumber = 1; while (1) { Check::CheckType CheckTy; size_t PrefixLoc; // See if a prefix occurs in the memory buffer. StringRef UsedPrefix = FindFirstMatchingPrefix(Buffer, LineNumber, CheckTy, PrefixLoc); if (UsedPrefix.empty()) break; Buffer = Buffer.drop_front(PrefixLoc); // Location to use for error messages. const char *UsedPrefixStart = Buffer.data() + (PrefixLoc == 0 ? 0 : 1); // PrefixLoc is to the start of the prefix. Skip to the end. Buffer = Buffer.drop_front(UsedPrefix.size() + CheckTypeSize(CheckTy)); // Okay, we found the prefix, yay. Remember the rest of the line, but ignore // leading and trailing whitespace. Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); // Scan ahead to the end of line. size_t EOL = Buffer.find_first_of("\n\r"); // Remember the location of the start of the pattern, for diagnostics. SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); // Parse the pattern. Pattern P(CheckTy); if (P.ParsePattern(Buffer.substr(0, EOL), UsedPrefix, SM, LineNumber)) return true; // Verify that CHECK-LABEL lines do not define or use variables if ((CheckTy == Check::CheckLabel) && P.hasVariable()) { SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error, "found '" + UsedPrefix + "-LABEL:'" " with variable definition or use"); return true; } Buffer = Buffer.substr(EOL); // Verify that CHECK-NEXT lines have at least one CHECK line before them. if ((CheckTy == Check::CheckNext) && CheckStrings.empty()) { SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error, "found '" + UsedPrefix + "-NEXT:' without previous '" + UsedPrefix + ": line"); return true; } // Handle CHECK-DAG/-NOT. if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) { DagNotMatches.push_back(P); continue; } // Okay, add the string we captured to the output vector and move on. CheckStrings.push_back(CheckString(P, UsedPrefix, PatternLoc, CheckTy)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); } // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first // prefix as a filler for the error message. if (!DagNotMatches.empty()) { CheckStrings.push_back(CheckString(Pattern(Check::CheckEOF), CheckPrefixes[0], SMLoc::getFromPointer(Buffer.data()), Check::CheckEOF)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); } if (CheckStrings.empty()) { errs() << "error: no check strings found with prefix" << (CheckPrefixes.size() > 1 ? "es " : " "); for (size_t I = 0, N = CheckPrefixes.size(); I != N; ++I) { StringRef Prefix(CheckPrefixes[I]); errs() << '\'' << Prefix << ":'"; if (I != N - 1) errs() << ", "; } errs() << '\n'; return true; } return false; }
size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector<const Pattern *> &NotStrings, StringMap<StringRef> &VariableTable) const { if (DagNotStrings.empty()) return 0; size_t LastPos = 0; size_t StartPos = LastPos; for (unsigned ChunkNo = 0, e = DagNotStrings.size(); ChunkNo != e; ++ChunkNo) { const Pattern &Pat = DagNotStrings[ChunkNo]; assert((Pat.getCheckTy() == Check::CheckDAG || Pat.getCheckTy() == Check::CheckNot) && "Invalid CHECK-DAG or CHECK-NOT!"); if (Pat.getCheckTy() == Check::CheckNot) { NotStrings.push_back(&Pat); continue; } assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!"); size_t MatchLen = 0, MatchPos; // CHECK-DAG always matches from the start. StringRef MatchBuffer = Buffer.substr(StartPos); MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable); // With a group of CHECK-DAGs, a single mismatching means the match on // that group of CHECK-DAGs fails immediately. if (MatchPos == StringRef::npos) { PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable); return StringRef::npos; } // Re-calc it as the offset relative to the start of the original string. MatchPos += StartPos; if (!NotStrings.empty()) { if (MatchPos < LastPos) { // Reordered? SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos), SourceMgr::DK_Error, Prefix + "-DAG: found a match of CHECK-DAG" " reordering across a CHECK-NOT"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos), SourceMgr::DK_Note, Prefix + "-DAG: the farthest match of CHECK-DAG" " is found here"); SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note, Prefix + "-NOT: the crossed pattern specified" " here"); SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note, Prefix + "-DAG: the reordered pattern specified" " here"); return StringRef::npos; } // All subsequent CHECK-DAGs should be matched from the farthest // position of all precedent CHECK-DAGs (including this one.) StartPos = LastPos; // If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to // CHECK-DAG, verify that there's no 'not' strings occurred in that // region. StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable)) return StringRef::npos; // Clear "not strings". NotStrings.clear(); } // Update the last position with CHECK-DAG matches. LastPos = std::max(MatchPos + MatchLen, LastPos); } return LastPos; }
int Disassembler::disassemble(const Target &T, const std::string &Triple, MCSubtargetInfo &STI, MCStreamer &Streamer, MemoryBuffer &Buffer, SourceMgr &SM, raw_ostream &Out) { std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple)); if (!MRI) { errs() << "error: no register info for target " << Triple << "\n"; return -1; } std::unique_ptr<const MCAsmInfo> MAI(T.createMCAsmInfo(*MRI, Triple)); if (!MAI) { errs() << "error: no assembly info for target " << Triple << "\n"; return -1; } // Set up the MCContext for creating symbols and MCExpr's. MCContext Ctx(MAI.get(), MRI.get(), nullptr); std::unique_ptr<const MCDisassembler> DisAsm( T.createMCDisassembler(STI, Ctx)); if (!DisAsm) { errs() << "error: no disassembler for target " << Triple << "\n"; return -1; } // Set up initial section manually here Streamer.InitSections(false); bool ErrorOccurred = false; // Convert the input to a vector for disassembly. ByteArrayTy ByteArray; StringRef Str = Buffer.getBuffer(); bool InAtomicBlock = false; while (SkipToToken(Str)) { ByteArray.first.clear(); ByteArray.second.clear(); if (Str[0] == '[') { if (InAtomicBlock) { SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, "nested atomic blocks make no sense"); ErrorOccurred = true; } InAtomicBlock = true; Str = Str.drop_front(); continue; } else if (Str[0] == ']') { if (!InAtomicBlock) { SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, "attempt to close atomic block without opening"); ErrorOccurred = true; } InAtomicBlock = false; Str = Str.drop_front(); continue; } // It's a real token, get the bytes and emit them ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM); if (!ByteArray.first.empty()) ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer, InAtomicBlock, STI); } if (InAtomicBlock) { SM.PrintMessage(SMLoc::getFromPointer(Str.data()), SourceMgr::DK_Error, "unclosed atomic block"); ErrorOccurred = true; } return ErrorOccurred; }