1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "MacroPPCallbacks.h" |
14 | #include "CGDebugInfo.h" |
15 | #include "clang/CodeGen/ModuleBuilder.h" |
16 | #include "clang/Lex/MacroInfo.h" |
17 | #include "clang/Lex/Preprocessor.h" |
18 | |
19 | using namespace clang; |
20 | |
21 | void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II, |
22 | const MacroInfo &MI, |
23 | Preprocessor &PP, raw_ostream &Name, |
24 | raw_ostream &Value) { |
25 | Name << II.getName(); |
26 | |
27 | if (MI.isFunctionLike()) { |
28 | Name << '('; |
29 | if (!MI.param_empty()) { |
30 | MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); |
31 | for (; AI + 1 != E; ++AI) { |
32 | Name << (*AI)->getName(); |
33 | Name << ','; |
34 | } |
35 | |
36 | |
37 | if ((*AI)->getName() == "__VA_ARGS__") |
38 | Name << "..."; |
39 | else |
40 | Name << (*AI)->getName(); |
41 | } |
42 | |
43 | if (MI.isGNUVarargs()) |
44 | |
45 | Name << "..."; |
46 | |
47 | Name << ')'; |
48 | } |
49 | |
50 | SmallString<128> SpellingBuffer; |
51 | bool First = true; |
52 | for (const auto &T : MI.tokens()) { |
53 | if (!First && T.hasLeadingSpace()) |
54 | Value << ' '; |
55 | |
56 | Value << PP.getSpelling(T, SpellingBuffer); |
57 | First = false; |
58 | } |
59 | } |
60 | |
61 | MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP) |
62 | : Gen(Gen), PP(PP), Status(NoScope) {} |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() { |
77 | if (Status == MainFileScope || Status == CommandLineIncludeScope) |
78 | return Scopes.back(); |
79 | return nullptr; |
80 | } |
81 | |
82 | SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) { |
83 | if (Status == MainFileScope || EnteredCommandLineIncludeFiles) |
84 | return Loc; |
85 | |
86 | |
87 | |
88 | return SourceLocation(); |
89 | } |
90 | |
91 | void MacroPPCallbacks::updateStatusToNextScope() { |
92 | switch (Status) { |
93 | case NoScope: |
94 | Status = InitializedScope; |
95 | break; |
96 | case InitializedScope: |
97 | Status = BuiltinScope; |
98 | break; |
99 | case BuiltinScope: |
100 | Status = CommandLineIncludeScope; |
101 | break; |
102 | case CommandLineIncludeScope: |
103 | Status = MainFileScope; |
104 | break; |
105 | case MainFileScope: |
106 | llvm_unreachable("There is no next scope, already in the final scope"); |
107 | } |
108 | } |
109 | |
110 | void MacroPPCallbacks::FileEntered(SourceLocation Loc) { |
111 | SourceLocation LineLoc = getCorrectLocation(LastHashLoc); |
112 | switch (Status) { |
113 | case NoScope: |
114 | updateStatusToNextScope(); |
115 | break; |
116 | case InitializedScope: |
117 | updateStatusToNextScope(); |
118 | return; |
119 | case BuiltinScope: |
120 | if (PP.getSourceManager().isWrittenInCommandLineFile(Loc)) |
121 | return; |
122 | updateStatusToNextScope(); |
123 | LLVM_FALLTHROUGH; |
124 | case CommandLineIncludeScope: |
125 | EnteredCommandLineIncludeFiles++; |
126 | break; |
127 | case MainFileScope: |
128 | break; |
129 | } |
130 | |
131 | Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(), |
132 | LineLoc, Loc)); |
133 | } |
134 | |
135 | void MacroPPCallbacks::FileExited(SourceLocation Loc) { |
136 | switch (Status) { |
137 | default: |
138 | llvm_unreachable("Do not expect to exit a file from current scope"); |
139 | case BuiltinScope: |
140 | if (!PP.getSourceManager().isWrittenInBuiltinFile(Loc)) |
141 | |
142 | Status = MainFileScope; |
143 | return; |
144 | case CommandLineIncludeScope: |
145 | if (!EnteredCommandLineIncludeFiles) { |
146 | updateStatusToNextScope(); |
147 | return; |
148 | } |
149 | EnteredCommandLineIncludeFiles--; |
150 | break; |
151 | case MainFileScope: |
152 | break; |
153 | } |
154 | |
155 | Scopes.pop_back(); |
156 | } |
157 | |
158 | void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, |
159 | SrcMgr::CharacteristicKind FileType, |
160 | FileID PrevFID) { |
161 | |
162 | if (Reason == EnterFile) |
163 | FileEntered(Loc); |
164 | else if (Reason == ExitFile) |
165 | FileExited(Loc); |
166 | } |
167 | |
168 | void MacroPPCallbacks::InclusionDirective( |
169 | SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, |
170 | bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, |
171 | StringRef SearchPath, StringRef RelativePath, const Module *Imported, |
172 | SrcMgr::CharacteristicKind FileType) { |
173 | |
174 | |
175 | LastHashLoc = HashLoc; |
176 | } |
177 | |
178 | void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok, |
179 | const MacroDirective *MD) { |
180 | IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); |
181 | SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); |
182 | std::string NameBuffer, ValueBuffer; |
183 | llvm::raw_string_ostream Name(NameBuffer); |
184 | llvm::raw_string_ostream Value(ValueBuffer); |
185 | writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value); |
186 | Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), |
187 | llvm::dwarf::DW_MACINFO_define, location, |
188 | Name.str(), Value.str()); |
189 | } |
190 | |
191 | void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok, |
192 | const MacroDefinition &MD, |
193 | const MacroDirective *Undef) { |
194 | IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); |
195 | SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); |
196 | Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), |
197 | llvm::dwarf::DW_MACINFO_undef, location, |
198 | Id->getName(), ""); |
199 | } |
200 | |