18#include "llvm/Config/config.h"
33struct PreprocessorDir {
62 const char *
Next = Str.begin();
69 const char *End = Str.end();
76 CurBuffer = SrcMgr.getMainFileID();
77 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
78 CurPtr = CurBuf.begin();
82 PrepIncludeStack.emplace_back();
88 if (End != MacroName.end())
90 "` specified on command line");
92 DefinedMacros.insert(MacroName);
113bool TGLexer::processEOF() {
114 SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
115 if (ParentIncludeLoc != SMLoc()) {
120 if (!prepExitInclude(
false))
123 CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
124 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
136 prepExitInclude(
true);
140int TGLexer::getNextChar() {
141 char CurChar = *CurPtr++;
144 return (
unsigned char)CurChar;
149 if (CurPtr - 1 == CurBuf.end()) {
154 "NUL character is invalid in source; treated as space");
163 if ((*CurPtr ==
'\n' || (*CurPtr ==
'\r')) && *CurPtr != CurChar)
169int TGLexer::peekNextChar(
int Index)
const {
return *(CurPtr +
Index); }
175 int CurChar = getNextChar();
181 return LexIdentifier();
184 return ReturnError(TokStart,
"unexpected character");
190 FileOrLineStart =
false;
222 if (FileOrLineStart) {
225 return lexPreprocessor(Kind);
233 if (peekNextChar(0) ==
'.') {
235 if (peekNextChar(0) ==
'.') {
239 return ReturnError(TokStart,
"invalid '..' punctuation");
252 FileOrLineStart =
true;
259 else if (*CurPtr ==
'*') {
263 return ReturnError(TokStart,
"unexpected character");
284 NextChar = peekNextChar(i++);
287 if (NextChar ==
'x' || NextChar ==
'b') {
290 int NextNextChar = peekNextChar(i);
291 switch (NextNextChar) {
327 return LexIdentifier();
345 const char *StrStart = CurPtr;
349 while (*CurPtr !=
'"') {
351 if (*CurPtr == 0 && CurPtr == CurBuf.end())
352 return ReturnError(StrStart,
"end of file in string literal");
354 if (*CurPtr ==
'\n' || *CurPtr ==
'\r')
355 return ReturnError(StrStart,
"end of line in string literal");
357 if (*CurPtr !=
'\\') {
358 CurStrVal += *CurPtr++;
369 CurStrVal += *CurPtr++;
382 return ReturnError(CurPtr,
"escaped newlines not supported in tblgen");
386 if (CurPtr == CurBuf.end())
387 return ReturnError(StrStart,
"end of file in string literal");
390 return ReturnError(CurPtr,
"invalid escape in string literal");
400 return ReturnError(TokStart,
"invalid variable name");
403 const char *VarNameStart = CurPtr++;
408 CurStrVal.assign(VarNameStart, CurPtr);
414 const char *IdentStart = TokStart;
421 StringRef Str(IdentStart, CurPtr - IdentStart);
459 CurStrVal.assign(Str.begin(), Str.end());
470bool TGLexer::LexInclude() {
482 std::string IncludedFile;
491 Dependencies.insert(IncludedFile);
493 CurBuf = SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer();
494 CurPtr = CurBuf.begin();
496 PrepIncludeStack.emplace_back();
502void TGLexer::SkipBCPLComment() {
504 auto EOLPos = CurBuf.find_first_of(
"\r\n", CurPtr - CurBuf.data());
505 CurPtr = (EOLPos ==
StringRef::npos) ? CurBuf.end() : CurBuf.data() + EOLPos;
510bool TGLexer::SkipCComment() {
512 unsigned CommentDepth = 1;
515 int CurChar = getNextChar();
522 if (CurPtr[0] !=
'/')
526 if (--CommentDepth == 0)
531 if (CurPtr[0] !=
'*')
546 const char *NumStart;
549 if (CurPtr[-1] ==
'0') {
550 NumStart = CurPtr + 1;
551 if (CurPtr[0] ==
'x') {
556 }
else if (CurPtr[0] ==
'b') {
560 while (CurPtr[0] ==
'0' || CurPtr[0] ==
'1');
565 bool IsMinus =
false;
571 if (CurPtr[-1] ==
'-')
573 else if (CurPtr[-1] ==
'+')
579 IsMinus = CurPtr[-1] ==
'-';
586 if (CurPtr == NumStart)
587 return ReturnError(TokStart,
"invalid number");
591 CurIntVal = strtoll(NumStart,
nullptr,
Base);
593 CurIntVal = strtoull(NumStart,
nullptr,
Base);
596 return ReturnError(TokStart,
"invalid number");
598 return ReturnError(TokStart,
"number out of range");
606 if (CurPtr[0] !=
'{')
609 const char *CodeStart = CurPtr;
611 int Char = getNextChar();
618 Char = getNextChar();
622 CurStrVal.assign(CodeStart, CurPtr - 2);
627 return ReturnError(CodeStart - 2,
"unterminated code block");
633 return ReturnError(CurPtr - 1,
"invalid \"!operator\"");
635 const char *
Start = CurPtr++;
641 StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start))
701 : ReturnError(Start - 1,
"unknown operator");
704bool TGLexer::prepExitInclude(
bool IncludeStackMustBeEmpty) {
707 if (!PrepIncludeStack.back().empty()) {
708 prepReportPreprocessorStackError();
714 PrepIncludeStack.pop_back();
716 if (IncludeStackMustBeEmpty) {
717 assert(PrepIncludeStack.empty() &&
718 "preprocessor include stack is not empty");
720 assert(!PrepIncludeStack.empty() &&
"preprocessor include stack is empty");
728 if (StringRef(CurPtr,
Word.size()) != Word)
730 int NextChar = peekNextChar(
Word.size());
737 if (NextChar ==
' ' || NextChar ==
'\t' || NextChar == EOF ||
757 if (NextChar ==
'/') {
758 NextChar = peekNextChar(
Word.size() + 1);
760 if (NextChar ==
'*' || NextChar ==
'/')
776 CurPtr += PWord.size();
782 "unsupported preprocessing token in prepEatPreprocessorDirective()");
786 bool ReturnNextLiveToken) {
788 prepEatPreprocessorDirective(Kind);
791 StringRef MacroName = prepLexMacroName();
793 if (MacroName.
empty())
794 return ReturnError(TokStart,
"expected macro name after " + IfTokName);
796 bool MacroIsDefined = DefinedMacros.count(MacroName) != 0;
800 MacroIsDefined = !MacroIsDefined;
805 PrepIncludeStack.back().push_back(
808 if (!prepSkipDirectiveEnd())
809 return ReturnError(CurPtr,
"only comments are supported after " +
810 IfTokName +
" NAME");
814 if (!ReturnNextLiveToken)
826 if (prepSkipRegion(ReturnNextLiveToken))
833 if (PrepIncludeStack.back().empty())
834 return ReturnError(TokStart,
"#else without #ifdef or #ifndef");
836 PreprocessorControlDesc IfdefEntry = PrepIncludeStack.back().back();
840 return ReturnError(IfdefEntry.SrcPos,
"previous #else is here");
845 PrepIncludeStack.back().back() = {
Kind, !IfdefEntry.IsDefined,
848 if (!prepSkipDirectiveEnd())
849 return ReturnError(CurPtr,
"only comments are supported after #else");
853 if (ReturnNextLiveToken) {
854 if (prepSkipRegion(ReturnNextLiveToken))
865 if (PrepIncludeStack.back().empty())
866 return ReturnError(TokStart,
"#endif without #ifdef");
868 [[maybe_unused]]
auto &IfdefOrElseEntry = PrepIncludeStack.back().back();
872 "invalid preprocessor control on the stack");
874 if (!prepSkipDirectiveEnd())
875 return ReturnError(CurPtr,
"only comments are supported after #endif");
877 PrepIncludeStack.back().pop_back();
881 if (ReturnNextLiveToken) {
888 StringRef MacroName = prepLexMacroName();
889 if (MacroName.
empty())
890 return ReturnError(TokStart,
"expected macro name after #define");
892 if (!DefinedMacros.insert(MacroName).second)
894 "duplicate definition of macro: " + Twine(MacroName));
896 if (!prepSkipDirectiveEnd())
897 return ReturnError(CurPtr,
898 "only comments are supported after #define NAME");
900 assert(ReturnNextLiveToken &&
901 "#define must be ignored during the lines skipping");
909bool TGLexer::prepSkipRegion(
bool MustNeverBeFalse) {
910 assert(MustNeverBeFalse &&
"invalid recursion.");
914 while (*CurPtr !=
'\n')
918 if (!prepSkipLineBegin())
946 assert(Kind == ProcessedKind &&
"prepIsDirective() and lexPreprocessor() "
947 "returned different token kinds");
953 if (prepIsProcessingEnabled()) {
955 "tokens processing was enabled by an unexpected preprocessing "
960 }
while (CurPtr != CurBuf.end());
964 prepReportPreprocessorStackError();
970 while (*CurPtr ==
' ' || *CurPtr ==
'\t')
974 CurPtr =
lexMacroName(StringRef(CurPtr, CurBuf.end() - CurPtr));
975 return StringRef(TokStart, CurPtr - TokStart);
978bool TGLexer::prepSkipLineBegin() {
979 while (CurPtr != CurBuf.end()) {
988 int NextChar = peekNextChar(1);
989 if (NextChar ==
'*') {
1027bool TGLexer::prepSkipDirectiveEnd() {
1028 while (CurPtr != CurBuf.end()) {
1039 int NextChar = peekNextChar(1);
1040 if (NextChar ==
'/') {
1046 }
else if (NextChar ==
'*') {
1088bool TGLexer::prepIsProcessingEnabled() {
1089 return all_of(PrepIncludeStack.back(),
1090 [](
const PreprocessorControlDesc &
I) { return I.IsDefined; });
1093void TGLexer::prepReportPreprocessorStackError() {
1094 auto &PrepControl = PrepIncludeStack.back().back();
1095 PrintError(CurBuf.end(),
"reached EOF without matching #endif");
1096 PrintError(PrepControl.SrcPos,
"the latest preprocessor control is here");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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),...
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.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
static constexpr size_t npos
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)
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.
FunctionAddr VTableAddr Next
bool isHexDigit(char C)
Checks if character C is a hexadecimal numeric character.