18#include "llvm/Config/config.h"
33struct PreprocessorDir {
45 if (
C ==
'_' || isAlpha(
C))
62 const char *Next = Str.begin();
69 const char *
End = Str.end();
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() {
115 if (ParentIncludeLoc !=
SMLoc()) {
120 if (!prepExitInclude(
false))
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);
494 CurPtr = CurBuf.
begin();
496 PrepIncludeStack.emplace_back();
502void TGLexer::SkipBCPLComment() {
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");
632 if (!isAlpha(*CurPtr))
633 return ReturnError(CurPtr - 1,
"invalid \"!operator\"");
635 const char *Start = CurPtr++;
636 while (isAlpha(*CurPtr))
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");
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')
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!")
static bool isDigit(const char C)
static bool isHexDigit(const char C)
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
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
LLVM_ABI 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.