aaboud updated this revision to Diff 86669.
aaboud marked an inline comment as done.
aaboud added a comment.
Address Adrian and Richard comments.
Please, review the new patch and let me know if I need to change anything else.
Thanks,
Amjad
https://reviews.llvm.org/D16135
Files:
include/clang/CodeGen/ModuleBuilder.h
lib/CodeGen/CGDebugInfo.cpp
lib/CodeGen/CGDebugInfo.h
lib/CodeGen/CMakeLists.txt
lib/CodeGen/CodeGenAction.cpp
lib/CodeGen/MacroPPCallbacks.cpp
lib/CodeGen/MacroPPCallbacks.h
lib/CodeGen/ModuleBuilder.cpp
test/CodeGen/debug-info-global-constant.c
Index: lib/CodeGen/ModuleBuilder.cpp
===================================================================
--- lib/CodeGen/ModuleBuilder.cpp
+++ lib/CodeGen/ModuleBuilder.cpp
@@ -92,6 +92,10 @@
return M.get();
}
+ CGDebugInfo *getCGDebugInfo() {
+ return Builder->getModuleDebugInfo();
+ }
+
llvm::Module *ReleaseModule() {
return M.release();
}
@@ -299,6 +303,10 @@
return static_cast<CodeGeneratorImpl*>(this)->ReleaseModule();
}
+CGDebugInfo *CodeGenerator::getCGDebugInfo() {
+ return static_cast<CodeGeneratorImpl*>(this)->getCGDebugInfo();
+}
+
const Decl *CodeGenerator::GetDeclForMangledName(llvm::StringRef name) {
return static_cast<CodeGeneratorImpl*>(this)->GetDeclForMangledName(name);
}
Index: lib/CodeGen/MacroPPCallbacks.h
===================================================================
--- lib/CodeGen/MacroPPCallbacks.h
+++ lib/CodeGen/MacroPPCallbacks.h
@@ -0,0 +1,107 @@
+//===--- MacroPPCallbacks.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines implementation for the macro preprocessors callbacks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/PPCallbacks.h"
+
+namespace llvm {
+class DIMacroFile;
+class DIMacroNode;
+}
+namespace clang {
+class Preprocessor;
+class MacroInfo;
+class CodeGenerator;
+
+class MacroPPCallbacks : public PPCallbacks {
+ /// A pointer to code generator, where debug info generator can be found.
+ CodeGenerator *Gen;
+
+ /// Preprocessor.
+ Preprocessor &PP;
+
+ /// Location of recent included file, used for line number.
+ SourceLocation LastHashLoc;
+
+ /// Location of main file, used for file info.
+ SourceLocation MainFileLoc;
+
+ /// Counts current number of command line included files, which was entered
+ /// and was not exited yet.
+ int CommandIncludeFiles = 0;
+
+ enum FileScopeStatus {
+ NoScope, // Scope is not initialized yet.
+ InitializedScope, // Main file scope is initialized but not set yet.
+ BuiltinScope, // <built-in> file scope.
+ CommandLineScope, // <command line> file scope.
+ CommandLineScopeIncludes, // Included file, from <command line> file, scope.
+ MainFileScope // Main file scope.
+ };
+ FileScopeStatus Status;
+
+ /// Parent contains all entered files that were not exited yet according to
+ /// the inclusion order.
+ llvm::SmallVector<llvm::DIMacroFile *, 4> Scopes;
+
+ /// Get current DIMacroFile scope.
+ /// \return current DIMacroFile scope or nullptr if there is no such scope.
+ llvm::DIMacroFile *getCurrentScope();
+
+ /// Get current line location or invalid location.
+ /// \param Loc current line location.
+ /// \return current line location \p `Loc`, or invalid location if it's in a
+ /// skipped file scope.
+ SourceLocation getCorrectLocation(SourceLocation Loc);
+
+ /// Use the passed preprocessor to calculate the macro name and value from
+ /// the given macro info and identifier info.
+ ///
+ /// \param II Identifier info, used to get the Macro name.
+ /// \param MI Macro info, used to get the Macro argumets and values.
+ /// \param PP Preprocessor.
+ /// \param [out] Name Place holder for returned macro name and arguments.
+ /// \param [out] Value Place holder for returned macro value.
+ static void calculatMacroDefinition(const IdentifierInfo &II,
+ const MacroInfo &MI, Preprocessor &PP,
+ raw_ostream &Name, raw_ostream &Value);
+
+public:
+ MacroPPCallbacks(CodeGenerator *Gen, Preprocessor &PP);
+
+ /// Callback invoked whenever a source file is entered or exited.
+ ///
+ /// \param Loc Indicates the new location.
+ /// \param PrevFID the file that was exited if \p Reason is ExitFile.
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID = FileID()) override;
+
+ /// Callback invoked whenever a directive (#xxx) is processed.
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported) override;
+
+ /// Hook called whenever a macro definition is seen.
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+
+ /// Hook called whenever a macro \#undef is seen.
+ ///
+ /// MD is released immediately following this callback.
+ void MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+};
+
+} // end namespace clang
Index: lib/CodeGen/CMakeLists.txt
===================================================================
--- lib/CodeGen/CMakeLists.txt
+++ lib/CodeGen/CMakeLists.txt
@@ -77,6 +77,7 @@
CodeGenTypes.cpp
CoverageMappingGen.cpp
ItaniumCXXABI.cpp
+ MacroPPCallbacks.cpp
MicrosoftCXXABI.cpp
ModuleBuilder.cpp
ObjectFilePCHContainerOperations.cpp
Index: lib/CodeGen/CGDebugInfo.h
===================================================================
--- lib/CodeGen/CGDebugInfo.h
+++ lib/CodeGen/CGDebugInfo.h
@@ -412,6 +412,15 @@
void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);
+ /// Get macro debug info.
+ llvm::DIMacro *CreateMacro(llvm::DIMacroFile *Parent, unsigned MType,
+ SourceLocation LineLoc, StringRef Name,
+ StringRef Value);
+
+ /// Get temporary macro file debug info.
+ llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent,
+ SourceLocation LineLoc,
+ SourceLocation FileLoc);
private:
/// Emit call to llvm.dbg.declare for a variable declaration.
void EmitDeclare(const VarDecl *decl, llvm::Value *AI,
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "CoverageMappingGen.h"
+#include "MacroPPCallbacks.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
@@ -99,6 +100,8 @@
I.second.release();
}
+ CodeGenerator *getCodeGenerator() { return Gen.get(); }
+
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
Gen->HandleCXXStaticMemberVarInstantiation(VD);
}
@@ -813,6 +816,15 @@
CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModules,
std::move(OS), *VMContext, CoverageInfo));
BEConsumer = Result.get();
+
+ // Enable generating macro debug info only in FullDebugInfo mode.
+ if (CI.getCodeGenOpts().getDebugInfo() == codegenoptions::FullDebugInfo) {
+ std::unique_ptr<PPCallbacks> Callbacks =
+ llvm::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(),
+ CI.getPreprocessor());
+ CI.getPreprocessor().addPPCallbacks(std::move(Callbacks));
+ }
+
return std::move(Result);
}
Index: lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- lib/CodeGen/CGDebugInfo.cpp
+++ lib/CodeGen/CGDebugInfo.cpp
@@ -2408,6 +2408,21 @@
FullName);
}
+llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
+ unsigned MType, SourceLocation LineLoc,
+ StringRef Name, StringRef Value) {
+ unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc);
+ return DBuilder.createMacro(Parent, Line, MType, Name, Value);
+}
+
+llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent,
+ SourceLocation LineLoc,
+ SourceLocation FileLoc) {
+ llvm::DIFile *FName = getOrCreateFile(FileLoc);
+ unsigned Line = LineLoc.isInvalid() ? 0 : getLineNumber(LineLoc);
+ return DBuilder.createTempMacroFile(Parent, Line, FName);
+}
+
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
Qualifiers Quals;
do {
Index: lib/CodeGen/MacroPPCallbacks.cpp
===================================================================
--- lib/CodeGen/MacroPPCallbacks.cpp
+++ lib/CodeGen/MacroPPCallbacks.cpp
@@ -0,0 +1,190 @@
+//===--- 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::calculatMacroDefinition(const IdentifierInfo &II,
+ const MacroInfo &MI,
+ Preprocessor &PP,
+ raw_ostream &Name,
+ raw_ostream &Value) {
+ Name << II.getName();
+
+ if (MI.isFunctionLike()) {
+ Name << '(';
+ if (!MI.arg_empty()) {
+ MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_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) {}
+
+llvm::DIMacroFile *MacroPPCallbacks::getCurrentScope() {
+ switch (Status) {
+ default:
+ return nullptr;
+ case CommandLineScopeIncludes:
+ case MainFileScope:
+ return Scopes.back();
+ }
+}
+
+SourceLocation MacroPPCallbacks::getCorrectLocation(SourceLocation Loc) {
+ switch (Status) {
+ default:
+ break;
+ case CommandLineScopeIncludes:
+ if (!CommandIncludeFiles)
+ break;
+ LLVM_FALLTHROUGH;
+ case MainFileScope:
+ return Loc;
+ }
+ // While parsing skipped files, location of macros is invalid.
+ // Invalid location represents line zero.
+ return SourceLocation();
+}
+
+void MacroPPCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) {
+ // Only care about enter file or exit file changes.
+ if (Reason != EnterFile && Reason != ExitFile)
+ return;
+
+ bool CreateMainFile = false;
+ bool CreateMacroFile = false;
+ bool PopScope = false;
+ SourceLocation LineLoc = getCorrectLocation(LastHashLoc);
+ switch (Status) {
+ case NoScope:
+ MainFileLoc = Loc;
+ Status = InitializedScope;
+ break;
+ case InitializedScope:
+ Status = BuiltinScope;
+ break;
+ case BuiltinScope:
+ Status = CommandLineScope;
+ break;
+ case CommandLineScope:
+ Status = CommandLineScopeIncludes;
+ CreateMainFile = true;
+ break;
+ case CommandLineScopeIncludes:
+ if (Reason == EnterFile) {
+ CommandIncludeFiles++;
+ CreateMacroFile = true;
+ } else if (Reason == ExitFile) {
+ if (!CommandIncludeFiles)
+ Status = MainFileScope;
+ else {
+ CommandIncludeFiles--;
+ PopScope = true;
+ }
+ }
+ break;
+ case MainFileScope:
+ if (Reason == EnterFile)
+ CreateMacroFile = true;
+ else if (Reason == ExitFile)
+ PopScope = true;
+ // No need to change status, already in the final status.
+ break;
+ }
+
+ if (CreateMainFile)
+ Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(
+ nullptr, LineLoc, MainFileLoc));
+ if (CreateMacroFile)
+ Scopes.push_back(Gen->getCGDebugInfo()->CreateTempMacroFile(
+ getCurrentScope(), LineLoc, Loc));
+ if (PopScope)
+ Scopes.pop_back();
+}
+
+void MacroPPCallbacks::InclusionDirective(
+ SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+ bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath, const Module *Imported) {
+ // Only care about "include" directives.
+ if (!IncludeTok.is(tok::identifier))
+ return;
+ auto PPKeywordID = IncludeTok.getIdentifierInfo()->getPPKeywordID();
+ switch (PPKeywordID) {
+ default:
+ return;
+ case tok::pp_include:
+ case tok::pp_include_next:
+ case tok::pp___include_macros:
+ break;
+ }
+
+ // 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);
+ calculatMacroDefinition(*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) {
+ IdentifierInfo *Id = MacroNameTok.getIdentifierInfo();
+ SourceLocation location = getCorrectLocation(MacroNameTok.getLocation());
+ Gen->getCGDebugInfo()->CreateMacro(getCurrentScope(),
+ llvm::dwarf::DW_MACINFO_undef, location,
+ Id->getName(), "");
+}
Index: include/clang/CodeGen/ModuleBuilder.h
===================================================================
--- include/clang/CodeGen/ModuleBuilder.h
+++ include/clang/CodeGen/ModuleBuilder.h
@@ -35,6 +35,7 @@
namespace CodeGen {
class CodeGenModule;
+ class CGDebugInfo;
}
/// The primary public interface to the Clang code generator.
@@ -65,6 +66,9 @@
/// CodeGenerator after releasing its module.
llvm::Module *ReleaseModule();
+ /// Return debug info code generator.
+ CodeGen::CGDebugInfo *getCGDebugInfo();
+
/// Given a mangled name, return a declaration which mangles that way
/// which has been added to this code generator via a Handle method.
///
Index: test/CodeGen/debug-info-global-constant.c
===================================================================
--- test/CodeGen/debug-info-global-constant.c
+++ test/CodeGen/debug-info-global-constant.c
@@ -7,7 +7,7 @@
// CHECK: @i = internal constant i32 1, align 4, !dbg ![[I:[0-9]+]]
// CHECK: ![[I]] = !DIGlobalVariableExpression(var: ![[VAR:.*]], expr: ![[EXPR:[0-9]+]])
// CHECK: ![[VAR]] = distinct !DIGlobalVariable(name: "i",
-// CHECK: !DICompileUnit({{.*}}globals: ![[GLOBALS:[0-9]+]])
+// CHECK: !DICompileUnit({{.*}}globals: ![[GLOBALS:[0-9]+]]
// CHECK: ![[GLOBALS]] = !{![[I]]}
// CHECK: ![[EXPR]] = !DIExpression(DW_OP_constu, 1, DW_OP_stack_value)
static const int i = 1;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits