/// getLineAndColumn - Find the line and column number for the specified /// location in the specified file. This is not a fast method. std::pair<unsigned, unsigned> SourceMgr::getLineAndColumn(SMLoc Loc, int BufferID) const { if (BufferID == -1) BufferID = FindBufferContainingLoc(Loc); assert(BufferID != -1 && "Invalid Location!"); MemoryBuffer *Buff = getBufferInfo(BufferID).Buffer; // Count the number of \n's between the start of the file and the specified // location. unsigned LineNo = 1; const char *BufStart = Buff->getBufferStart(); const char *Ptr = BufStart; // If we have a line number cache, and if the query is to a later point in the // same file, start searching from the last query location. This optimizes // for the case when multiple diagnostics come out of one file in order. if (LineNoCacheTy *Cache = getCache(LineNoCache)) if (Cache->LastQueryBufferID == BufferID && Cache->LastQuery <= Loc.getPointer()) { Ptr = Cache->LastQuery; LineNo = Cache->LineNoOfQuery; } // Scan for the location being queried, keeping track of the number of lines // we see. for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr) if (*Ptr == '\n') ++LineNo; // Allocate the line number cache if it doesn't exist. if (LineNoCache == 0) LineNoCache = new LineNoCacheTy(); // Update the line # cache. LineNoCacheTy &Cache = *getCache(LineNoCache); Cache.LastQueryBufferID = BufferID; Cache.LastQuery = Ptr; Cache.LineNoOfQuery = LineNo; size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r"); if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0; return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs); }
OperandMatchResultTy BPFAsmParser::parseRegister(OperandVector &Operands) { SMLoc S = getLoc(); SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; case AsmToken::Identifier: StringRef Name = getLexer().getTok().getIdentifier(); unsigned RegNo = MatchRegisterName(Name); if (RegNo == 0) return MatchOperand_NoMatch; getLexer().Lex(); Operands.push_back(BPFOperand::createReg(RegNo, S, E)); } return MatchOperand_Success; }
/// ParseInstruction - Parse an BPF instruction which is in BPF verifier /// format. bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { // The first operand could be either register or actually an operator. unsigned RegNo = MatchRegisterName(Name); if (RegNo != 0) { SMLoc E = SMLoc::getFromPointer(NameLoc.getPointer() - 1); Operands.push_back(BPFOperand::createReg(RegNo, NameLoc, E)); } else if (BPFOperand::isValidIdAtStart (Name)) Operands.push_back(BPFOperand::createToken(Name, NameLoc)); else return Error(NameLoc, "invalid register/token name"); while (!getLexer().is(AsmToken::EndOfStatement)) { // Attempt to parse token as operator if (parseOperandAsOperator(Operands) == MatchOperand_Success) continue; // Attempt to parse token as register if (parseRegister(Operands) == MatchOperand_Success) continue; // Attempt to parse token as an immediate if (parseImmediate(Operands) != MatchOperand_Success) { SMLoc Loc = getLexer().getLoc(); return Error(Loc, "unexpected token"); } } if (getLexer().isNot(AsmToken::EndOfStatement)) { SMLoc Loc = getLexer().getLoc(); getParser().eatToEndOfStatement(); return Error(Loc, "unexpected token"); } // Consume the EndOfStatement. getParser().Lex(); return false; }
int TGLexer::getNextChar() { char CurChar = *CurPtr++; switch (CurChar) { default: return (unsigned char)CurChar; case 0: { // A nul character in the stream is either the end of the current buffer or // a random nul in the file. Disambiguate that here. if (CurPtr-1 != CurBuf->getBufferEnd()) return 0; // Just whitespace. // If this is the end of an included file, pop the parent file off the // include stack. SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); if (ParentIncludeLoc != SMLoc()) { CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); CurPtr = ParentIncludeLoc.getPointer(); return getNextChar(); } // Otherwise, return end of file. --CurPtr; // Another call to lex will return EOF again. return EOF; } case '\n': case '\r': // Handle the newline character by ignoring it and incrementing the line // count. However, be careful about 'dos style' files with \n\r in them. // Only treat a \n\r or \r\n as a single line. if ((*CurPtr == '\n' || (*CurPtr == '\r')) && *CurPtr != CurChar) ++CurPtr; // Eat the two char newline sequence. return '\n'; } }
OperandMatchResultTy BPFAsmParser::parseImmediate(OperandVector &Operands) { switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; case AsmToken::LParen: case AsmToken::Minus: case AsmToken::Plus: case AsmToken::Integer: case AsmToken::String: case AsmToken::Identifier: break; } const MCExpr *IdVal; SMLoc S = getLoc(); if (getParser().parseExpression(IdVal)) return MatchOperand_ParseFail; SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); Operands.push_back(BPFOperand::createImm(IdVal, S, E)); return MatchOperand_Success; }
SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges, ArrayRef<SMFixIt> FixIts) const { // First thing to do: find the current buffer containing the specified // location to pull out the source line. SmallVector<std::pair<unsigned, unsigned>, 4> ColRanges; std::pair<unsigned, unsigned> LineAndCol; const char *BufferID = "<unknown>"; std::string LineStr; if (Loc.isValid()) { unsigned CurBuf = FindBufferContainingLoc(Loc); assert(CurBuf && "Invalid or unspecified location!"); const MemoryBuffer *CurMB = getMemoryBuffer(CurBuf); BufferID = CurMB->getBufferIdentifier(); // Scan backward to find the start of the line. const char *LineStart = Loc.getPointer(); const char *BufStart = CurMB->getBufferStart(); while (LineStart != BufStart && LineStart[-1] != '\n' && LineStart[-1] != '\r') --LineStart; // Get the end of the line. const char *LineEnd = Loc.getPointer(); const char *BufEnd = CurMB->getBufferEnd(); while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r') ++LineEnd; LineStr = std::string(LineStart, LineEnd); // Convert any ranges to column ranges that only intersect the line of the // location. for (unsigned i = 0, e = Ranges.size(); i != e; ++i) { SMRange R = Ranges[i]; if (!R.isValid()) continue; // If the line doesn't contain any part of the range, then ignore it. if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart) continue; // Ignore pieces of the range that go onto other lines. if (R.Start.getPointer() < LineStart) R.Start = SMLoc::getFromPointer(LineStart); if (R.End.getPointer() > LineEnd) R.End = SMLoc::getFromPointer(LineEnd); // Translate from SMLoc ranges to column ranges. // FIXME: Handle multibyte characters. ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart, R.End.getPointer()-LineStart)); } LineAndCol = getLineAndColumn(Loc, CurBuf); } return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first, LineAndCol.second-1, Kind, Msg.str(), LineStr, ColRanges, FixIts); }
/// parseDirectiveSection: /// ::= .section identifier (',' identifier)* bool DarwinAsmParser::parseDirectiveSection(StringRef, SMLoc) { SMLoc Loc = getLexer().getLoc(); StringRef SectionName; if (getParser().parseIdentifier(SectionName)) return Error(Loc, "expected identifier after '.section' directive"); // Verify there is a following comma. if (!getLexer().is(AsmToken::Comma)) return TokError("unexpected token in '.section' directive"); std::string SectionSpec = SectionName; SectionSpec += ","; // Add all the tokens until the end of the line, ParseSectionSpecifier will // handle this. StringRef EOL = getLexer().LexUntilEndOfStatement(); SectionSpec.append(EOL.begin(), EOL.end()); Lex(); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.section' directive"); Lex(); StringRef Segment, Section; unsigned StubSize; unsigned TAA; bool TAAParsed; std::string ErrorStr = MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, TAA, TAAParsed, StubSize); if (!ErrorStr.empty()) return Error(Loc, ErrorStr.c_str()); // Issue a warning if the target is not powerpc and Section is a *coal* section. Triple TT = getParser().getContext().getObjectFileInfo()->getTargetTriple(); Triple::ArchType ArchTy = TT.getArch(); if (ArchTy != Triple::ppc && ArchTy != Triple::ppc64) { StringRef NonCoalSection = StringSwitch<StringRef>(Section) .Case("__textcoal_nt", "__text") .Case("__const_coal", "__const") .Case("__datacoal_nt", "__data") .Default(Section); if (!Section.equals(NonCoalSection)) { StringRef SectionVal(Loc.getPointer()); size_t B = SectionVal.find(',') + 1, E = SectionVal.find(',', B); SMLoc BLoc = SMLoc::getFromPointer(SectionVal.data() + B); SMLoc ELoc = SMLoc::getFromPointer(SectionVal.data() + E); getParser().Warning(Loc, "section \"" + Section + "\" is deprecated", SMRange(BLoc, ELoc)); getParser().Note(Loc, "change section name to \"" + NonCoalSection + "\"", SMRange(BLoc, ELoc)); } } // FIXME: Arch specific. bool isText = Segment == "__TEXT"; // FIXME: Hack. getStreamer().SwitchSection(getContext().getMachOSection( Segment, Section, TAA, StubSize, isText ? SectionKind::getText() : SectionKind::getDataRel())); return false; }