18#include "llvm/Config/config.h"
35struct PreprocessorDir {
47 if (
C ==
'_' || isAlpha(
C))
64 const char *Next = Str.begin();
71 const char *
End = Str.end();
80 CurPtr = CurBuf.
begin();
84 PrepIncludeStack.emplace_back();
90 if (
End != MacroName.end())
92 "` specified on command line");
94 DefinedMacros.
insert(MacroName);
117bool TGLexer::processEOF() {
119 if (ParentIncludeLoc !=
SMLoc()) {
124 if (!prepExitInclude(
false))
140 prepExitInclude(
true);
144int TGLexer::getNextChar() {
145 char CurChar = *CurPtr++;
148 return (
unsigned char)CurChar;
153 if (CurPtr - 1 == CurBuf.
end()) {
158 "NUL character is invalid in source; treated as space");
167 if ((*CurPtr ==
'\n' || (*CurPtr ==
'\r')) &&
174int TGLexer::peekNextChar(
int Index)
const {
175 return *(CurPtr +
Index);
181 int CurChar = getNextChar();
187 return LexIdentifier();
190 return ReturnError(TokStart,
"unexpected character");
216 if (FileOrLineStart) {
219 return lexPreprocessor(Kind);
227 if (peekNextChar(0) ==
'.') {
229 if (peekNextChar(0) ==
'.') {
233 return ReturnError(TokStart,
"invalid '..' punctuation");
243 return LexToken(FileOrLineStart);
246 return LexToken(
true);
252 else if (*CurPtr ==
'*') {
256 return ReturnError(TokStart,
"unexpected character");
257 return LexToken(FileOrLineStart);
259 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
260 case '7':
case '8':
case '9': {
268 NextChar = peekNextChar(i++);
271 if (NextChar ==
'x' || NextChar ==
'b') {
274 int NextNextChar = peekNextChar(i);
275 switch (NextNextChar) {
282 case '2':
case '3':
case '4':
case '5':
283 case '6':
case '7':
case '8':
case '9':
284 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
285 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
294 return LexIdentifier();
298 case '"':
return LexString();
299 case '$':
return LexVarName();
300 case '[':
return LexBracket();
301 case '!':
return LexExclaim();
307 const char *StrStart = CurPtr;
311 while (*CurPtr !=
'"') {
313 if (*CurPtr == 0 && CurPtr == CurBuf.
end())
314 return ReturnError(StrStart,
"end of file in string literal");
316 if (*CurPtr ==
'\n' || *CurPtr ==
'\r')
317 return ReturnError(StrStart,
"end of line in string literal");
319 if (*CurPtr !=
'\\') {
320 CurStrVal += *CurPtr++;
327 case '\\':
case '\'':
case '"':
329 CurStrVal += *CurPtr++;
342 return ReturnError(CurPtr,
"escaped newlines not supported in tblgen");
346 if (CurPtr == CurBuf.
end())
347 return ReturnError(StrStart,
"end of file in string literal");
350 return ReturnError(CurPtr,
"invalid escape in string literal");
360 return ReturnError(TokStart,
"invalid variable name");
363 const char *VarNameStart = CurPtr++;
368 CurStrVal.assign(VarNameStart, CurPtr);
374 const char *IdentStart = TokStart;
381 StringRef Str(IdentStart, CurPtr-IdentStart);
418 CurStrVal.assign(Str.begin(), Str.end());
429bool TGLexer::LexInclude() {
440 std::string IncludedFile;
449 Dependencies.insert(IncludedFile);
452 CurPtr = CurBuf.
begin();
454 PrepIncludeStack.emplace_back();
460void TGLexer::SkipBCPLComment() {
468bool TGLexer::SkipCComment() {
470 unsigned CommentDepth = 1;
473 int CurChar = getNextChar();
480 if (CurPtr[0] !=
'/')
break;
483 if (--CommentDepth == 0)
488 if (CurPtr[0] !=
'*')
break;
502 const char *NumStart;
505 if (CurPtr[-1] ==
'0') {
506 NumStart = CurPtr + 1;
507 if (CurPtr[0] ==
'x') {
512 }
else if (CurPtr[0] ==
'b') {
516 while (CurPtr[0] ==
'0' || CurPtr[0] ==
'1');
521 bool IsMinus =
false;
527 if (CurPtr[-1] ==
'-')
529 else if (CurPtr[-1] ==
'+')
535 IsMinus = CurPtr[-1] ==
'-';
542 if (CurPtr == NumStart)
543 return ReturnError(TokStart,
"invalid number");
547 CurIntVal = strtoll(NumStart,
nullptr,
Base);
549 CurIntVal = strtoull(NumStart,
nullptr,
Base);
552 return ReturnError(TokStart,
"invalid number");
554 return ReturnError(TokStart,
"number out of range");
562 if (CurPtr[0] !=
'{')
565 const char *CodeStart = CurPtr;
567 int Char = getNextChar();
568 if (Char == EOF)
break;
570 if (Char !=
'}')
continue;
572 Char = getNextChar();
573 if (Char == EOF)
break;
575 CurStrVal.assign(CodeStart, CurPtr-2);
580 return ReturnError(CodeStart - 2,
"unterminated code block");
585 if (!isAlpha(*CurPtr))
586 return ReturnError(CurPtr - 1,
"invalid \"!operator\"");
588 const char *Start = CurPtr++;
589 while (isAlpha(*CurPtr))
650 : ReturnError(Start - 1,
"unknown operator");
653bool TGLexer::prepExitInclude(
bool IncludeStackMustBeEmpty) {
656 if (!PrepIncludeStack.back().empty()) {
657 prepReportPreprocessorStackError();
663 PrepIncludeStack.pop_back();
665 if (IncludeStackMustBeEmpty) {
666 assert(PrepIncludeStack.empty() &&
667 "preprocessor include stack is not empty");
669 assert(!PrepIncludeStack.empty() &&
"preprocessor include stack is empty");
679 int NextChar = peekNextChar(
Word.size());
686 if (NextChar ==
' ' || NextChar ==
'\t' || NextChar == EOF ||
706 if (NextChar ==
'/') {
707 NextChar = peekNextChar(
Word.size() + 1);
709 if (NextChar ==
'*' || NextChar ==
'/')
725 CurPtr += PWord.size();
731 "unsupported preprocessing token in prepEatPreprocessorDirective()");
735 bool ReturnNextLiveToken) {
737 prepEatPreprocessorDirective(Kind);
740 StringRef MacroName = prepLexMacroName();
742 if (MacroName.
empty())
743 return ReturnError(TokStart,
"expected macro name after " + IfTokName);
745 bool MacroIsDefined = DefinedMacros.
count(MacroName) != 0;
749 MacroIsDefined = !MacroIsDefined;
754 PrepIncludeStack.back().push_back(
757 if (!prepSkipDirectiveEnd())
758 return ReturnError(CurPtr,
"only comments are supported after " +
759 IfTokName +
" NAME");
763 if (!ReturnNextLiveToken)
775 if (prepSkipRegion(ReturnNextLiveToken))
782 if (PrepIncludeStack.back().empty())
783 return ReturnError(TokStart,
"#else without #ifdef or #ifndef");
785 PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back().back();
789 return ReturnError(IfdefEntry.SrcPos,
"previous #else is here");
794 PrepIncludeStack.back().back() = {
Kind, !IfdefEntry.IsDefined,
797 if (!prepSkipDirectiveEnd())
798 return ReturnError(CurPtr,
"only comments are supported after #else");
802 if (ReturnNextLiveToken) {
803 if (prepSkipRegion(ReturnNextLiveToken))
814 if (PrepIncludeStack.back().empty())
815 return ReturnError(TokStart,
"#endif without #ifdef");
817 [[maybe_unused]]
auto &IfdefOrElseEntry = PrepIncludeStack.back().back();
821 "invalid preprocessor control on the stack");
823 if (!prepSkipDirectiveEnd())
824 return ReturnError(CurPtr,
"only comments are supported after #endif");
826 PrepIncludeStack.back().pop_back();
830 if (ReturnNextLiveToken) {
837 StringRef MacroName = prepLexMacroName();
838 if (MacroName.
empty())
839 return ReturnError(TokStart,
"expected macro name after #define");
841 if (!DefinedMacros.
insert(MacroName).second)
843 "duplicate definition of macro: " +
Twine(MacroName));
845 if (!prepSkipDirectiveEnd())
846 return ReturnError(CurPtr,
847 "only comments are supported after #define NAME");
849 assert(ReturnNextLiveToken &&
850 "#define must be ignored during the lines skipping");
858bool TGLexer::prepSkipRegion(
bool MustNeverBeFalse) {
859 assert(MustNeverBeFalse &&
"invalid recursion.");
863 while (*CurPtr !=
'\n')
867 if (!prepSkipLineBegin())
895 assert(Kind == ProcessedKind &&
"prepIsDirective() and lexPreprocessor() "
896 "returned different token kinds");
902 if (prepIsProcessingEnabled()) {
904 "tokens processing was enabled by an unexpected preprocessing "
909 }
while (CurPtr != CurBuf.
end());
913 prepReportPreprocessorStackError();
919 while (*CurPtr ==
' ' || *CurPtr ==
'\t')
924 return StringRef(TokStart, CurPtr - TokStart);
927bool TGLexer::prepSkipLineBegin() {
928 while (CurPtr != CurBuf.
end()) {
937 int NextChar = peekNextChar(1);
938 if (NextChar ==
'*') {
976bool TGLexer::prepSkipDirectiveEnd() {
977 while (CurPtr != CurBuf.
end()) {
988 int NextChar = peekNextChar(1);
989 if (NextChar ==
'/') {
995 }
else if (NextChar ==
'*') {
1037bool TGLexer::prepIsProcessingEnabled() {
1038 return all_of(PrepIncludeStack.back(),
1039 [](
const PreprocessorControlDesc &
I) { return I.IsDefined; });
1042void TGLexer::prepReportPreprocessorStackError() {
1043 auto &PrepControl = PrepIncludeStack.back().back();
1044 PrintError(CurBuf.
end(),
"reached EOF without matching #endif");
1045 PrintError(PrepControl.SrcPos,
"the latest preprocessor control is here");
static bool isDigit(const char C)
static bool isHexDigit(const char C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
constexpr PreprocessorDir PreprocessorDirs[]
static bool isValidIDChar(char C, bool First)
Returns true if C is a valid character in an identifier.
static const char * lexMacroName(StringRef Str)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
StringRef getBuffer() const
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
Represents a range in source code.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
unsigned getMainFileID() const
const MemoryBuffer * getMemoryBuffer(unsigned i) const
SMLoc getParentIncludeLoc(unsigned i) const
unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
static constexpr size_t npos
std::pair< typename Base::iterator, bool > insert(StringRef key)
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
SMRange getLocRange() const
TGLexer(SourceMgr &SrcMgr, ArrayRef< std::string > Macros)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
support::ulittle32_t Word
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
void PrintFatalError(const Twine &Msg)
void PrintError(const Twine &Msg)
void PrintWarning(const Twine &Msg)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.