18#include "llvm/Config/config.h"
32struct PreprocessorDir {
61 const char *
Next = Str.begin();
68 const char *End = Str.end();
75 CurBuffer = SrcMgr.getMainFileID();
76 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
77 CurPtr = CurBuf.begin();
81 PrepIncludeStack.emplace_back();
87 if (End != MacroName.end())
89 "` specified on command line");
91 DefinedMacros.insert(MacroName);
112bool TGLexer::processEOF() {
113 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
114 if (ParentIncludeLoc != SMLoc()) {
119 if (!prepExitInclude(
false))
122 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
123 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
135 prepExitInclude(
true);
139int TGLexer::getNextChar() {
140 char CurChar = *CurPtr++;
143 return (
unsigned char)CurChar;
148 if (CurPtr - 1 == CurBuf.end()) {
153 "NUL character is invalid in source; treated as space");
162 if ((*CurPtr ==
'\n' || (*CurPtr ==
'\r')) && *CurPtr != CurChar)
168int TGLexer::peekNextChar(
int Index)
const {
return *(CurPtr +
Index); }
174 int CurChar = getNextChar();
180 return LexIdentifier();
183 return ReturnError(TokStart,
"unexpected character");
189 FileOrLineStart =
false;
221 if (FileOrLineStart) {
224 return lexPreprocessor(Kind);
232 if (peekNextChar(0) ==
'.') {
234 if (peekNextChar(0) ==
'.') {
238 return ReturnError(TokStart,
"invalid '..' punctuation");
251 FileOrLineStart =
true;
258 else if (*CurPtr ==
'*') {
262 return ReturnError(TokStart,
"unexpected character");
283 NextChar = peekNextChar(i++);
286 if (NextChar ==
'x' || NextChar ==
'b') {
289 int NextNextChar = peekNextChar(i);
290 switch (NextNextChar) {
326 return LexIdentifier();
344 const char *StrStart = CurPtr;
348 while (*CurPtr !=
'"') {
350 if (*CurPtr == 0 && CurPtr == CurBuf.end())
351 return ReturnError(StrStart,
"end of file in string literal");
353 if (*CurPtr ==
'\n' || *CurPtr ==
'\r')
354 return ReturnError(StrStart,
"end of line in string literal");
356 if (*CurPtr !=
'\\') {
357 CurStrVal += *CurPtr++;
368 CurStrVal += *CurPtr++;
381 return ReturnError(CurPtr,
"escaped newlines not supported in tblgen");
385 if (CurPtr == CurBuf.end())
386 return ReturnError(StrStart,
"end of file in string literal");
389 return ReturnError(CurPtr,
"invalid escape in string literal");
399 return ReturnError(TokStart,
"invalid variable name");
402 const char *VarNameStart = CurPtr++;
407 CurStrVal.assign(VarNameStart, CurPtr);
413 const char *IdentStart = TokStart;
420 StringRef Str(IdentStart, CurPtr - IdentStart);
458 CurStrVal.assign(Str.begin(), Str.end());
469bool TGLexer::LexInclude() {
481 std::string IncludedFile;
490 Dependencies.insert(IncludedFile);
492 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
493 CurPtr = CurBuf.
begin();
495 PrepIncludeStack.emplace_back();
501void TGLexer::SkipBCPLComment() {
503 auto EOLPos = CurBuf.find_first_of(
"\r\n", CurPtr - CurBuf.data());
504 CurPtr = (EOLPos ==
StringRef::npos) ? CurBuf.end() : CurBuf.data() + EOLPos;
509bool TGLexer::SkipCComment() {
511 unsigned CommentDepth = 1;
514 int CurChar = getNextChar();
521 if (CurPtr[0] !=
'/')
525 if (--CommentDepth == 0)
530 if (CurPtr[0] !=
'*')
545 const char *NumStart;
548 if (CurPtr[-1] ==
'0') {
549 NumStart = CurPtr + 1;
550 if (CurPtr[0] ==
'x') {
555 }
else if (CurPtr[0] ==
'b') {
559 while (CurPtr[0] ==
'0' || CurPtr[0] ==
'1');
564 bool IsMinus =
false;
570 if (CurPtr[-1] ==
'-')
572 else if (CurPtr[-1] ==
'+')
578 IsMinus = CurPtr[-1] ==
'-';
585 if (CurPtr == NumStart)
586 return ReturnError(TokStart,
"invalid number");
590 CurIntVal = strtoll(NumStart,
nullptr,
Base);
592 CurIntVal = strtoull(NumStart,
nullptr,
Base);
595 return ReturnError(TokStart,
"invalid number");
597 return ReturnError(TokStart,
"number out of range");
605 if (CurPtr[0] !=
'{')
608 const char *CodeStart = CurPtr;
610 int Char = getNextChar();
617 Char = getNextChar();
621 CurStrVal.assign(CodeStart, CurPtr - 2);
626 return ReturnError(CodeStart - 2,
"unterminated code block");
632 return ReturnError(CurPtr - 1,
"invalid \"!operator\"");
634 const char *
Start = CurPtr++;
640 StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
702 : ReturnError(Start - 1,
"unknown operator");
705bool TGLexer::prepExitInclude(
bool IncludeStackMustBeEmpty) {
708 if (!PrepIncludeStack.back().empty()) {
709 prepReportPreprocessorStackError();
715 PrepIncludeStack.pop_back();
717 if (IncludeStackMustBeEmpty) {
718 assert(PrepIncludeStack.empty() &&
719 "preprocessor include stack is not empty");
721 assert(!PrepIncludeStack.empty() &&
"preprocessor include stack is empty");
729 if (StringRef(CurPtr,
Word.size()) != Word)
731 int NextChar = peekNextChar(
Word.size());
738 if (NextChar ==
' ' || NextChar ==
'\t' || NextChar == EOF ||
758 if (NextChar ==
'/') {
759 NextChar = peekNextChar(
Word.size() + 1);
761 if (NextChar ==
'*' || NextChar ==
'/')
777 CurPtr += PWord.size();
783 "unsupported preprocessing token in prepEatPreprocessorDirective()");
787 bool ReturnNextLiveToken) {
789 prepEatPreprocessorDirective(Kind);
792 StringRef MacroName = prepLexMacroName();
794 if (MacroName.
empty())
795 return ReturnError(TokStart,
"expected macro name after " + IfTokName);
797 bool MacroIsDefined = DefinedMacros.count(MacroName) != 0;
801 MacroIsDefined = !MacroIsDefined;
806 PrepIncludeStack.back().push_back(
809 if (!prepSkipDirectiveEnd())
810 return ReturnError(CurPtr,
"only comments are supported after " +
811 IfTokName +
" NAME");
815 if (!ReturnNextLiveToken)
827 if (prepSkipRegion(ReturnNextLiveToken))
834 if (PrepIncludeStack.back().empty())
835 return ReturnError(TokStart,
"#else without #ifdef or #ifndef");
837 PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back().back();
841 return ReturnError(IfdefEntry.SrcPos,
"previous #else is here");
846 PrepIncludeStack.back().back() = {
Kind, !IfdefEntry.IsDefined,
849 if (!prepSkipDirectiveEnd())
850 return ReturnError(CurPtr,
"only comments are supported after #else");
854 if (ReturnNextLiveToken) {
855 if (prepSkipRegion(ReturnNextLiveToken))
866 if (PrepIncludeStack.back().empty())
867 return ReturnError(TokStart,
"#endif without #ifdef");
869 [[maybe_unused]]
auto &IfdefOrElseEntry = PrepIncludeStack.back().back();
873 "invalid preprocessor control on the stack");
875 if (!prepSkipDirectiveEnd())
876 return ReturnError(CurPtr,
"only comments are supported after #endif");
878 PrepIncludeStack.back().pop_back();
882 if (ReturnNextLiveToken) {
889 StringRef MacroName = prepLexMacroName();
890 if (MacroName.
empty())
891 return ReturnError(TokStart,
"expected macro name after #define");
893 if (!DefinedMacros.insert(MacroName).second)
895 "duplicate definition of macro: " + Twine(MacroName));
897 if (!prepSkipDirectiveEnd())
898 return ReturnError(CurPtr,
899 "only comments are supported after #define NAME");
901 assert(ReturnNextLiveToken &&
902 "#define must be ignored during the lines skipping");
910bool TGLexer::prepSkipRegion(
bool MustNeverBeFalse) {
911 assert(MustNeverBeFalse &&
"invalid recursion.");
915 while (CurPtr != CurBuf.end() && *CurPtr !=
'\n' && *CurPtr !=
'\r')
919 if (!prepSkipLineBegin())
947 assert(Kind == ProcessedKind &&
"prepIsDirective() and lexPreprocessor() "
948 "returned different token kinds");
954 if (prepIsProcessingEnabled()) {
956 "tokens processing was enabled by an unexpected preprocessing "
961 }
while (CurPtr != CurBuf.end());
965 prepReportPreprocessorStackError();
971 while (*CurPtr ==
' ' || *CurPtr ==
'\t')
975 CurPtr =
lexMacroName(StringRef(CurPtr, CurBuf.end() - CurPtr));
976 return StringRef(TokStart, CurPtr - TokStart);
979bool TGLexer::prepSkipLineBegin() {
980 while (CurPtr != CurBuf.end()) {
989 int NextChar = peekNextChar(1);
990 if (NextChar ==
'*') {
1028bool TGLexer::prepSkipDirectiveEnd() {
1029 while (CurPtr != CurBuf.end()) {
1040 int NextChar = peekNextChar(1);
1041 if (NextChar ==
'/') {
1047 }
else if (NextChar ==
'*') {
1089bool TGLexer::prepIsProcessingEnabled() {
1090 return all_of(PrepIncludeStack.back(),
1091 [](
const PreprocessorControlDesc &
I) { return I.IsDefined; });
1094void TGLexer::prepReportPreprocessorStackError() {
1095 auto &PrepControl = PrepIncludeStack.back().back();
1096 PrintError(CurBuf.end(),
"reached EOF without matching #endif");
1097 PrintError(PrepControl.SrcPos,
"the latest preprocessor control is here");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static constexpr StringLiteral Filename
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)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
Represent a constant reference to a string, i.e.
static constexpr size_t npos
constexpr bool empty() const
Check if the string is empty.
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.
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.
LLVM_ABI void PrintFatalError(const Twine &Msg)
LLVM_ABI void PrintError(const Twine &Msg)
LLVM_ABI void PrintWarning(const Twine &Msg)
bool isAlpha(char C)
Checks if character C is a valid letter as classified by "C" locale.
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool isHexDigit(char C)
Checks if character C is a hexadecimal numeric character.