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.push_back(
85 std::make_unique<std::vector<PreprocessorControlDesc>>());
91 if (
End != MacroName.end())
93 "` specified on command line");
95 DefinedMacros.
insert(MacroName);
118bool TGLexer::processEOF() {
120 if (ParentIncludeLoc !=
SMLoc()) {
125 if (!prepExitInclude(
false))
141 prepExitInclude(
true);
145int TGLexer::getNextChar() {
146 char CurChar = *CurPtr++;
149 return (
unsigned char)CurChar;
154 if (CurPtr - 1 == CurBuf.
end()) {
159 "NUL character is invalid in source; treated as space");
168 if ((*CurPtr ==
'\n' || (*CurPtr ==
'\r')) &&
175int TGLexer::peekNextChar(
int Index)
const {
176 return *(CurPtr +
Index);
182 int CurChar = getNextChar();
188 return LexIdentifier();
191 return ReturnError(TokStart,
"Unexpected character");
217 if (FileOrLineStart) {
220 return lexPreprocessor(Kind);
228 if (peekNextChar(0) ==
'.') {
230 if (peekNextChar(0) ==
'.') {
234 return ReturnError(TokStart,
"Invalid '..' punctuation");
245 return LexToken(FileOrLineStart);
248 return LexToken(
true);
254 else if (*CurPtr ==
'*') {
258 return ReturnError(TokStart,
"Unexpected character");
259 return LexToken(FileOrLineStart);
261 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
262 case '7':
case '8':
case '9': {
270 NextChar = peekNextChar(i++);
273 if (NextChar ==
'x' || NextChar ==
'b') {
276 int NextNextChar = peekNextChar(i);
277 switch (NextNextChar) {
284 case '2':
case '3':
case '4':
case '5':
285 case '6':
case '7':
case '8':
case '9':
286 case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
287 case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
296 return LexIdentifier();
300 case '"':
return LexString();
301 case '$':
return LexVarName();
302 case '[':
return LexBracket();
303 case '!':
return LexExclaim();
309 const char *StrStart = CurPtr;
313 while (*CurPtr !=
'"') {
315 if (*CurPtr == 0 && CurPtr == CurBuf.
end())
316 return ReturnError(StrStart,
"End of file in string literal");
318 if (*CurPtr ==
'\n' || *CurPtr ==
'\r')
319 return ReturnError(StrStart,
"End of line in string literal");
321 if (*CurPtr !=
'\\') {
322 CurStrVal += *CurPtr++;
329 case '\\':
case '\'':
case '"':
331 CurStrVal += *CurPtr++;
344 return ReturnError(CurPtr,
"escaped newlines not supported in tblgen");
348 if (CurPtr == CurBuf.
end())
349 return ReturnError(StrStart,
"End of file in string literal");
352 return ReturnError(CurPtr,
"invalid escape in string literal");
362 return ReturnError(TokStart,
"Invalid variable name");
365 const char *VarNameStart = CurPtr++;
370 CurStrVal.assign(VarNameStart, CurPtr);
376 const char *IdentStart = TokStart;
383 StringRef Str(IdentStart, CurPtr-IdentStart);
420 CurStrVal.assign(Str.begin(), Str.end());
431bool TGLexer::LexInclude() {
442 std::string IncludedFile;
451 Dependencies.insert(IncludedFile);
454 CurPtr = CurBuf.
begin();
456 PrepIncludeStack.push_back(
457 std::make_unique<std::vector<PreprocessorControlDesc>>());
463void TGLexer::SkipBCPLComment() {
471bool TGLexer::SkipCComment() {
473 unsigned CommentDepth = 1;
476 int CurChar = getNextChar();
479 PrintError(TokStart,
"Unterminated comment!");
483 if (CurPtr[0] !=
'/')
break;
486 if (--CommentDepth == 0)
491 if (CurPtr[0] !=
'*')
break;
505 const char *NumStart;
508 if (CurPtr[-1] ==
'0') {
509 NumStart = CurPtr + 1;
510 if (CurPtr[0] ==
'x') {
515 }
else if (CurPtr[0] ==
'b') {
519 while (CurPtr[0] ==
'0' || CurPtr[0] ==
'1');
524 bool IsMinus =
false;
530 if (CurPtr[-1] ==
'-')
532 else if (CurPtr[-1] ==
'+')
538 IsMinus = CurPtr[-1] ==
'-';
545 if (CurPtr == NumStart)
546 return ReturnError(TokStart,
"Invalid number");
550 CurIntVal = strtoll(NumStart,
nullptr,
Base);
552 CurIntVal = strtoull(NumStart,
nullptr,
Base);
555 return ReturnError(TokStart,
"Invalid number");
557 return ReturnError(TokStart,
"Number out of range");
565 if (CurPtr[0] !=
'{')
568 const char *CodeStart = CurPtr;
570 int Char = getNextChar();
571 if (Char == EOF)
break;
573 if (Char !=
'}')
continue;
575 Char = getNextChar();
576 if (Char == EOF)
break;
578 CurStrVal.assign(CodeStart, CurPtr-2);
583 return ReturnError(CodeStart - 2,
"Unterminated code block");
588 if (!isAlpha(*CurPtr))
589 return ReturnError(CurPtr - 1,
"Invalid \"!operator\"");
591 const char *Start = CurPtr++;
592 while (isAlpha(*CurPtr))
653bool TGLexer::prepExitInclude(
bool IncludeStackMustBeEmpty) {
656 if (!PrepIncludeStack.back()->empty()) {
657 prepReportPreprocessorStackError();
663 if (PrepIncludeStack.empty()) {
667 PrepIncludeStack.pop_back();
669 if (IncludeStackMustBeEmpty) {
670 if (!PrepIncludeStack.empty())
673 if (PrepIncludeStack.empty())
684 int NextChar = peekNextChar(
Word.size());
691 if (NextChar ==
' ' || NextChar ==
'\t' || NextChar == EOF ||
711 if (NextChar ==
'/') {
712 NextChar = peekNextChar(
Word.size() + 1);
714 if (NextChar ==
'*' || NextChar ==
'/')
730 CurPtr += PWord.size();
735 "prepEatPreprocessorDirective()");
740 bool ReturnNextLiveToken) {
742 if (!prepEatPreprocessorDirective(Kind))
744 "preprocessor directive");
747 StringRef MacroName = prepLexMacroName();
749 if (MacroName.
empty())
750 return ReturnError(TokStart,
"Expected macro name after " + IfTokName);
752 bool MacroIsDefined = DefinedMacros.
count(MacroName) != 0;
756 MacroIsDefined = !MacroIsDefined;
761 PrepIncludeStack.back()->push_back(
764 if (!prepSkipDirectiveEnd())
765 return ReturnError(CurPtr,
"Only comments are supported after " +
766 IfTokName +
" NAME");
770 if (!ReturnNextLiveToken)
782 if (prepSkipRegion(ReturnNextLiveToken))
789 if (PrepIncludeStack.back()->empty())
790 return ReturnError(TokStart,
"#else without #ifdef or #ifndef");
792 PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back()->back();
796 return ReturnError(IfdefEntry.SrcPos,
"Previous #else is here");
801 PrepIncludeStack.back()->pop_back();
802 PrepIncludeStack.back()->push_back(
805 if (!prepSkipDirectiveEnd())
806 return ReturnError(CurPtr,
"Only comments are supported after #else");
810 if (ReturnNextLiveToken) {
811 if (prepSkipRegion(ReturnNextLiveToken))
822 if (PrepIncludeStack.back()->empty())
823 return ReturnError(TokStart,
"#endif without #ifdef");
825 auto &IfdefOrElseEntry = PrepIncludeStack.back()->back();
833 if (!prepSkipDirectiveEnd())
834 return ReturnError(CurPtr,
"Only comments are supported after #endif");
836 PrepIncludeStack.back()->pop_back();
840 if (ReturnNextLiveToken) {
847 StringRef MacroName = prepLexMacroName();
848 if (MacroName.
empty())
849 return ReturnError(TokStart,
"Expected macro name after #define");
851 if (!DefinedMacros.
insert(MacroName).second)
853 "Duplicate definition of macro: " +
Twine(MacroName));
855 if (!prepSkipDirectiveEnd())
856 return ReturnError(CurPtr,
857 "Only comments are supported after #define NAME");
859 if (!ReturnNextLiveToken) {
871bool TGLexer::prepSkipRegion(
bool MustNeverBeFalse) {
872 if (!MustNeverBeFalse)
877 while (*CurPtr !=
'\n')
881 if (!prepSkipLineBegin())
909 if (Kind != ProcessedKind)
911 "returned different token kinds");
917 if (prepIsProcessingEnabled()) {
920 "preprocessing directive");
926 }
while (CurPtr != CurBuf.
end());
930 prepReportPreprocessorStackError();
936 while (*CurPtr ==
' ' || *CurPtr ==
'\t')
941 return StringRef(TokStart, CurPtr - TokStart);
944bool TGLexer::prepSkipLineBegin() {
945 while (CurPtr != CurBuf.
end()) {
954 int NextChar = peekNextChar(1);
955 if (NextChar ==
'*') {
993bool TGLexer::prepSkipDirectiveEnd() {
994 while (CurPtr != CurBuf.
end()) {
1005 int NextChar = peekNextChar(1);
1006 if (NextChar ==
'/') {
1012 }
else if (NextChar ==
'*') {
1054bool TGLexer::prepIsProcessingEnabled() {
1055 for (
const PreprocessorControlDesc &
I :
1063void TGLexer::prepReportPreprocessorStackError() {
1064 if (PrepIncludeStack.back()->empty())
1066 "empty control stack");
1068 auto &PrepControl = PrepIncludeStack.back()->back();
1069 PrintError(CurBuf.
end(),
"Reached EOF without matching #endif");
1070 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...
@ C
The default llvm calling convention, compatible with C.
support::ulittle32_t Word
This is an optimization pass for GlobalISel generic memory operations.
void PrintFatalError(const Twine &Msg)
void PrintError(const Twine &Msg)
void PrintWarning(const Twine &Msg)
auto reverse(ContainerTy &&C)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.