diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp b/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp new file mode 100644 index 0000000..a6f21d8 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/CodeGen/MacroPPCallbacks.cpp @@ -0,0 +1,208 @@ +//===--- MacroPPCallbacks.cpp ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains implementation for the macro preprocessors callbacks. +// +//===----------------------------------------------------------------------===// + +#include "MacroPPCallbacks.h" +#include "CGDebugInfo.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Parse/Parser.h" + +using namespace clang; + +void MacroPPCallbacks::writeMacroDefinition(const IdentifierInfo &II, + const MacroInfo &MI, + Preprocessor &PP, raw_ostream &Name, + raw_ostream &Value) { + Name << II.getName(); + + if (MI.isFunctionLike()) { + Name << '('; + if (!MI.param_empty()) { + MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); + for (; AI + 1 != E; ++AI) { + Name << (*AI)->getName(); + Name << ','; + } + + // Last argument. + if ((*AI)->getName() == "__VA_ARGS__") + Name << "..."; + else + Name << (*AI)->getName(); + } + + if (MI.isGNUVarargs()) + // #define foo(x...) + Name << "..."; + + Name << ')'; + } + + SmallString<128> SpellingBuffer; + bool First = true; + for (const auto &T : MI.tokens()) { + if (!First && T.hasLeadingSpace()) + Value << ' '; + + Value << PP.getSpelling(T, SpellingBuffer); + First = false; + } +} + +MacroPPCallbacks::MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP) + : Gen(Gen), PP(PP), Status(NoScope) {} + +// This is the expected flow of enter/exit compiler and user files: +// - Main File Enter +// - <built-in> file enter +// {Compiler macro definitions} - (Line=0, no scope) +// - (Optional) <command line> file enter +// {Command line macro definitions} - (Line=0, no scope) +// - (Optional) <command line> file exit +// {Command line file includes} - (Line=0, Main file scope) +// {macro definitions and file includes} - (Line!=0, Parent scope) +// - <built-in> file exit +// {User code macro definitions and file includes} - (Line!=0, Parent scope) + +llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() { + if (Status == MainFileScope || Status == CommandLineIncludeScope) + return Scopes.back(); + return nullptr; +} + +SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) { + if (Status == MainFileScope || EnteredCommandLineIncludeFiles) + return Loc; + + // While parsing skipped files, location of macros is invalid. + // Invalid location represents line zero. + return SourceLocation(); +} + +static bool isBuiltinFile(SourceManager &SM, SourceLocation Loc) { + StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); + return Filename.equals("<built-in>"); +} + +static bool isCommandLineFile(SourceManager &SM, SourceLocation Loc) { + StringRef Filename(SM.getPresumedLoc(Loc).getFilename()); + return Filename.equals("<command line>"); +} + +void MacroPPCallbacks::updateStatusToNextScope() { + switch (Status) { + case NoScope: + Status = InitializedScope; + break; + case InitializedScope: + Status = BuiltinScope; + break; + case BuiltinScope: + Status = CommandLineIncludeScope; + break; + case CommandLineIncludeScope: + Status = MainFileScope; + break; + case MainFileScope: + llvm_unreachable("There is no next scope, already in the final scope"); + } +} + +void MacroPPCallbacks::FileEntered(SourceLocation Loc) { + SourceLocation LineLoc = getCorrectLocation(LastHashLoc); + switch (Status) { + case NoScope: + updateStatusToNextScope(); + break; + case InitializedScope: + updateStatusToNextScope(); + return; + case BuiltinScope: + if (isCommandLineFile(PP.getSourceManager(), Loc)) + return; + updateStatusToNextScope(); + LLVM_FALLTHROUGH; + case CommandLineIncludeScope: + EnteredCommandLineIncludeFiles++; + break; + case MainFileScope: + break; + } + + Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(getCurrentScope(), + LineLoc, Loc)); +} + +void MacroPPCallbacks::FileExited(SourceLocation Loc) { + switch (Status) { + default: + llvm_unreachable("Do not expect to exit a file from current scope"); + case BuiltinScope: + if (!isBuiltinFile(PP.getSourceManager(), Loc)) + // Skip next scope and change status to MainFileScope. + Status = MainFileScope; + return; + case CommandLineIncludeScope: + if (!EnteredCommandLineIncludeFiles) { + updateStatusToNextScope(); + return; + } + EnteredCommandLineIncludeFiles--; + break; + case MainFileScope: + break; + } + + Scopes.pop_back(); +} + +void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, + SrcMgr::CharacteristicKind FileType, + FileID PrevFID) { + // Only care about enter file or exit file changes. + if (Reason == EnterFile) + FileEntered(Loc); + else if (Reason == ExitFile) + FileExited(Loc); +} + +void MacroPPCallbacks::InclusionDirective( + SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, + bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, + StringRef SearchPath, StringRef RelativePath, const Module *Imported) { + + // Record the line location of the current included file. + LastHashLoc = HashLoc; +} + +void MacroPPCallbacks::MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) { + IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); + SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); + std::string NameBuffer, ValueBuffer; + llvm::raw_string_ostream Name(NameBuffer); + llvm::raw_string_ostream Value(ValueBuffer); + writeMacroDefinition(*Id, *MD->getMacroInfo(), PP, Name, Value); + Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), + llvm::dwarf::DW_MACINFO_define, location, + Name.str(), Value.str()); +} + +void MacroPPCallbacks::MacroUndefined(const Token &MacroNameTok, + const MacroDefinition &MD, + const MacroDirective *Undef) { + IdentifierInfo *Id = MacroNameTok.getIdentifierInfo(); + SourceLocation location = getCorrectLocation(MacroNameTok.getLocation()); + Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(), + llvm::dwarf::DW_MACINFO_undef, location, + Id->getName(), ""); +} |