1546bc110SAmjad Aboud //===--- MacroPPCallbacks.cpp ---------------------------------------------===//
2546bc110SAmjad Aboud //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6546bc110SAmjad Aboud //
7546bc110SAmjad Aboud //===----------------------------------------------------------------------===//
8546bc110SAmjad Aboud //
9546bc110SAmjad Aboud // This file contains implementation for the macro preprocessors callbacks.
10546bc110SAmjad Aboud //
11546bc110SAmjad Aboud //===----------------------------------------------------------------------===//
12546bc110SAmjad Aboud
13546bc110SAmjad Aboud #include "MacroPPCallbacks.h"
14546bc110SAmjad Aboud #include "CGDebugInfo.h"
15546bc110SAmjad Aboud #include "clang/CodeGen/ModuleBuilder.h"
16994b8befSRichard Trieu #include "clang/Lex/MacroInfo.h"
17994b8befSRichard Trieu #include "clang/Lex/Preprocessor.h"
18546bc110SAmjad Aboud
19546bc110SAmjad Aboud using namespace clang;
20546bc110SAmjad Aboud
writeMacroDefinition(const IdentifierInfo & II,const MacroInfo & MI,Preprocessor & PP,raw_ostream & Name,raw_ostream & Value)21546bc110SAmjad Aboud void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II,
22546bc110SAmjad Aboud const MacroInfo &MI,
23546bc110SAmjad Aboud Preprocessor &PP, raw_ostream &Name,
24546bc110SAmjad Aboud raw_ostream &Value) {
25546bc110SAmjad Aboud Name << II.getName();
26546bc110SAmjad Aboud
27546bc110SAmjad Aboud if (MI.isFunctionLike()) {
28546bc110SAmjad Aboud Name << '(';
29ac506d74SFaisal Vali if (!MI.param_empty()) {
30ac506d74SFaisal Vali MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end();
31546bc110SAmjad Aboud for (; AI + 1 != E; ++AI) {
32546bc110SAmjad Aboud Name << (*AI)->getName();
33546bc110SAmjad Aboud Name << ',';
34546bc110SAmjad Aboud }
35546bc110SAmjad Aboud
36546bc110SAmjad Aboud // Last argument.
37546bc110SAmjad Aboud if ((*AI)->getName() == "__VA_ARGS__")
38546bc110SAmjad Aboud Name << "...";
39546bc110SAmjad Aboud else
40546bc110SAmjad Aboud Name << (*AI)->getName();
41546bc110SAmjad Aboud }
42546bc110SAmjad Aboud
43546bc110SAmjad Aboud if (MI.isGNUVarargs())
44546bc110SAmjad Aboud // #define foo(x...)
45546bc110SAmjad Aboud Name << "...";
46546bc110SAmjad Aboud
47546bc110SAmjad Aboud Name << ')';
48546bc110SAmjad Aboud }
49546bc110SAmjad Aboud
50546bc110SAmjad Aboud SmallString<128> SpellingBuffer;
51546bc110SAmjad Aboud bool First = true;
52546bc110SAmjad Aboud for (const auto &T : MI.tokens()) {
53546bc110SAmjad Aboud if (!First && T.hasLeadingSpace())
54546bc110SAmjad Aboud Value << ' ';
55546bc110SAmjad Aboud
56546bc110SAmjad Aboud Value << PP.getSpelling(T, SpellingBuffer);
57546bc110SAmjad Aboud First = false;
58546bc110SAmjad Aboud }
59546bc110SAmjad Aboud }
60546bc110SAmjad Aboud
MacroPPCallbacks(CodeGenerator * Gen,Preprocessor & PP)61546bc110SAmjad Aboud MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP)
62546bc110SAmjad Aboud : Gen(Gen), PP(PP), Status(NoScope) {}
63546bc110SAmjad Aboud
64cdbfd0edSEric Christopher // This is the expected flow of enter/exit compiler and user files:
65cdbfd0edSEric Christopher // - Main File Enter
66cdbfd0edSEric Christopher // - <built-in> file enter
67cdbfd0edSEric Christopher // {Compiler macro definitions} - (Line=0, no scope)
68cdbfd0edSEric Christopher // - (Optional) <command line> file enter
69cdbfd0edSEric Christopher // {Command line macro definitions} - (Line=0, no scope)
70cdbfd0edSEric Christopher // - (Optional) <command line> file exit
71cdbfd0edSEric Christopher // {Command line file includes} - (Line=0, Main file scope)
72cdbfd0edSEric Christopher // {macro definitions and file includes} - (Line!=0, Parent scope)
73cdbfd0edSEric Christopher // - <built-in> file exit
74cdbfd0edSEric Christopher // {User code macro definitions and file includes} - (Line!=0, Parent scope)
75546bc110SAmjad Aboud
getCurrentScope()76546bc110SAmjad Aboud llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {
77546bc110SAmjad Aboud if (Status == MainFileScope || Status == CommandLineIncludeScope)
78546bc110SAmjad Aboud return Scopes.back();
79546bc110SAmjad Aboud return nullptr;
80546bc110SAmjad Aboud }
81546bc110SAmjad Aboud
getCorrectLocation(SourceLocation Loc)82546bc110SAmjad Aboud SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
83546bc110SAmjad Aboud if (Status == MainFileScope || EnteredCommandLineIncludeFiles)
84546bc110SAmjad Aboud return Loc;
85546bc110SAmjad Aboud
86546bc110SAmjad Aboud // While parsing skipped files, location of macros is invalid.
87546bc110SAmjad Aboud // Invalid location represents line zero.
88546bc110SAmjad Aboud return SourceLocation();
89546bc110SAmjad Aboud }
90546bc110SAmjad Aboud
updateStatusToNextScope()91546bc110SAmjad Aboud void MacroPPCallbacks::updateStatusToNextScope() {
92546bc110SAmjad Aboud switch (Status) {
93546bc110SAmjad Aboud case NoScope:
94546bc110SAmjad Aboud Status = InitializedScope;
95546bc110SAmjad Aboud break;
96546bc110SAmjad Aboud case InitializedScope:
97546bc110SAmjad Aboud Status = BuiltinScope;
98546bc110SAmjad Aboud break;
99546bc110SAmjad Aboud case BuiltinScope:
100546bc110SAmjad Aboud Status = CommandLineIncludeScope;
101546bc110SAmjad Aboud break;
102546bc110SAmjad Aboud case CommandLineIncludeScope:
103546bc110SAmjad Aboud Status = MainFileScope;
104546bc110SAmjad Aboud break;
105546bc110SAmjad Aboud case MainFileScope:
106546bc110SAmjad Aboud llvm_unreachable("There is no next scope, already in the final scope");
107546bc110SAmjad Aboud }
108546bc110SAmjad Aboud }
109546bc110SAmjad Aboud
FileEntered(SourceLocation Loc)110546bc110SAmjad Aboud void MacroPPCallbacks::FileEntered(SourceLocation Loc) {
111546bc110SAmjad Aboud SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
112546bc110SAmjad Aboud switch (Status) {
113546bc110SAmjad Aboud case NoScope:
114546bc110SAmjad Aboud updateStatusToNextScope();
115546bc110SAmjad Aboud break;
116546bc110SAmjad Aboud case InitializedScope:
117546bc110SAmjad Aboud updateStatusToNextScope();
118546bc110SAmjad Aboud return;
119546bc110SAmjad Aboud case BuiltinScope:
120a32a2e34SRoman Lebedev if (PP.getSourceManager().isWrittenInCommandLineFile(Loc))
121546bc110SAmjad Aboud return;
122546bc110SAmjad Aboud updateStatusToNextScope();
123546bc110SAmjad Aboud LLVM_FALLTHROUGH;
124546bc110SAmjad Aboud case CommandLineIncludeScope:
125546bc110SAmjad Aboud EnteredCommandLineIncludeFiles++;
126546bc110SAmjad Aboud break;
127546bc110SAmjad Aboud case MainFileScope:
128546bc110SAmjad Aboud break;
129546bc110SAmjad Aboud }
130546bc110SAmjad Aboud
131546bc110SAmjad Aboud Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(),
132546bc110SAmjad Aboud LineLoc, Loc));
133546bc110SAmjad Aboud }
134546bc110SAmjad Aboud
FileExited(SourceLocation Loc)135546bc110SAmjad Aboud void MacroPPCallbacks::FileExited(SourceLocation Loc) {
136546bc110SAmjad Aboud switch (Status) {
137546bc110SAmjad Aboud default:
138546bc110SAmjad Aboud llvm_unreachable("Do not expect to exit a file from current scope");
139546bc110SAmjad Aboud case BuiltinScope:
140a32a2e34SRoman Lebedev if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc))
141546bc110SAmjad Aboud // Skip next scope and change status to MainFileScope.
142546bc110SAmjad Aboud Status = MainFileScope;
143546bc110SAmjad Aboud return;
144546bc110SAmjad Aboud case CommandLineIncludeScope:
145546bc110SAmjad Aboud if (!EnteredCommandLineIncludeFiles) {
146546bc110SAmjad Aboud updateStatusToNextScope();
147546bc110SAmjad Aboud return;
148546bc110SAmjad Aboud }
149546bc110SAmjad Aboud EnteredCommandLineIncludeFiles--;
150546bc110SAmjad Aboud break;
151546bc110SAmjad Aboud case MainFileScope:
152546bc110SAmjad Aboud break;
153546bc110SAmjad Aboud }
154546bc110SAmjad Aboud
155546bc110SAmjad Aboud Scopes.pop_back();
156546bc110SAmjad Aboud }
157546bc110SAmjad Aboud
FileChanged(SourceLocation Loc,FileChangeReason Reason,SrcMgr::CharacteristicKind FileType,FileID PrevFID)158546bc110SAmjad Aboud void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
159546bc110SAmjad Aboud SrcMgr::CharacteristicKind FileType,
160546bc110SAmjad Aboud FileID PrevFID) {
161546bc110SAmjad Aboud // Only care about enter file or exit file changes.
162546bc110SAmjad Aboud if (Reason == EnterFile)
163546bc110SAmjad Aboud FileEntered(Loc);
164546bc110SAmjad Aboud else if (Reason == ExitFile)
165546bc110SAmjad Aboud FileExited(Loc);
166546bc110SAmjad Aboud }
167546bc110SAmjad Aboud
InclusionDirective(SourceLocation HashLoc,const Token & IncludeTok,StringRef FileName,bool IsAngled,CharSourceRange FilenameRange,Optional<FileEntryRef> File,StringRef SearchPath,StringRef RelativePath,const Module * Imported,SrcMgr::CharacteristicKind FileType)168546bc110SAmjad Aboud void MacroPPCallbacks::InclusionDirective(
169546bc110SAmjad Aboud SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
170*d79ad2f1SJan Svoboda bool IsAngled, CharSourceRange FilenameRange, Optional<FileEntryRef> File,
17196fbe58bSJulie Hockett StringRef SearchPath, StringRef RelativePath, const Module *Imported,
17296fbe58bSJulie Hockett SrcMgr::CharacteristicKind FileType) {
173546bc110SAmjad Aboud
174546bc110SAmjad Aboud // Record the line location of the current included file.
175546bc110SAmjad Aboud LastHashLoc = HashLoc;
176546bc110SAmjad Aboud }
177546bc110SAmjad Aboud
MacroDefined(const Token & MacroNameTok,const MacroDirective * MD)178546bc110SAmjad Aboud void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok,
179546bc110SAmjad Aboud const MacroDirective *MD) {
180546bc110SAmjad Aboud IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
181546bc110SAmjad Aboud SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
182546bc110SAmjad Aboud std::string NameBuffer, ValueBuffer;
183546bc110SAmjad Aboud llvm::raw_string_ostream Name(NameBuffer);
184546bc110SAmjad Aboud llvm::raw_string_ostream Value(ValueBuffer);
185546bc110SAmjad Aboud writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value);
186546bc110SAmjad Aboud Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
187546bc110SAmjad Aboud llvm::dwarf::DW_MACINFO_define, location,
188546bc110SAmjad Aboud Name.str(), Value.str());
189546bc110SAmjad Aboud }
190546bc110SAmjad Aboud
MacroUndefined(const Token & MacroNameTok,const MacroDefinition & MD,const MacroDirective * Undef)191546bc110SAmjad Aboud void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok,
192204103f3SDavid Blaikie const MacroDefinition &MD,
193204103f3SDavid Blaikie const MacroDirective *Undef) {
194546bc110SAmjad Aboud IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
195546bc110SAmjad Aboud SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
196546bc110SAmjad Aboud Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
197546bc110SAmjad Aboud llvm::dwarf::DW_MACINFO_undef, location,
198546bc110SAmjad Aboud Id->getName(), "");
199546bc110SAmjad Aboud }
200