Debug Info: Migrate from MDModule to DIModule.

MDModule was a bitcode-incompatible internal-only extension that has
since been replaced with a blessed IR node on trunk.

<rdar://problem/20965932> Upstream DIModule and support it in clang-700, swiftlang-700, and lldb-700

Swift SVN r29832
This commit is contained in:
Adrian Prantl
2015-07-01 02:25:22 +00:00
parent dd44dad017
commit c5dd8bea82
8 changed files with 88 additions and 124 deletions

View File

@@ -72,30 +72,6 @@ StringRef IRGenDebugInfo::BumpAllocatedString(StringRef S) {
return BumpAllocatedString(S.data(), S.size());
}
static bool isNonAscii(StringRef str) {
for (unsigned char c : str) {
if (c >= 0x80)
return true;
}
return false;
}
// Mangle a single non-operator identifier.
static void mangleIdent(llvm::raw_string_ostream &OS, StringRef Id) {
// If the identifier contains non-ASCII character, we mangle with an initial
// X and Punycode the identifier string.
std::string PunycodeBuf;
(void) isNonAscii;
if (isNonAscii(Id)) {
OS << 'X';
Punycode::encodePunycodeUTF8(Id, PunycodeBuf);
Id = PunycodeBuf;
}
OS << Id.size() << Id;
OS.flush();
return;
}
/// Return the size reported by a type.
static unsigned getSizeInBits(llvm::DIType *Ty, const TrackingDIRefMap &Map) {
// Follow derived types until we reach a type that
@@ -191,14 +167,9 @@ IRGenDebugInfo::IRGenDebugInfo(const IRGenOptions &Opts,
}
// Create a module for the current compile unit.
MainModule = getOrCreateModule(TheCU, Opts.ModuleName, MainFile);
std::string Mangled("_TF");
llvm::raw_string_ostream MS(Mangled);
if (Opts.ModuleName == IGM.Context.StdlibModuleName.str())
MS << "S";
else
mangleIdent(MS, Opts.ModuleName);
createImportedModule(Opts.ModuleName, MS.str(), MainModule, 1);
MainModule =
getOrCreateModule(Opts.ModuleName, TheCU, Opts.ModuleName, MainFilename);
DBuilder.createImportedModule(MainFile, MainModule, 1);
}
static const char *getFilenameFromDC(const DeclContext *DC) {
@@ -587,17 +558,15 @@ llvm::DIScope *IRGenDebugInfo::getOrCreateContext(DeclContext *DC) {
case DeclContextKind::AbstractFunctionDecl:
// We don't model these in DWARF.
case DeclContextKind::SerializedLocal:
case DeclContextKind::Initializer:
case DeclContextKind::ExtensionDecl:
return getOrCreateContext(DC->getParent());
case DeclContextKind::TopLevelCodeDecl:
return cast<llvm::DIScope>(EntryPointFn);
case DeclContextKind::Module: {
auto File = getOrCreateFile(getFilenameFromDC(DC));
return getOrCreateModule(TheCU, cast<Module>(DC)->getName().str(), File);
}
case DeclContextKind::Module:
return getOrCreateModule({Module::AccessPathTy(), cast<ModuleDecl>(DC)});
case DeclContextKind::FileUnit:
// A module may contain multiple files.
return getOrCreateContext(DC->getParent());
@@ -788,69 +757,60 @@ void IRGenDebugInfo::emitImport(ImportDecl *D) {
if (Opts.DebugInfoKind == IRGenDebugInfoKind::LineTables)
return;
// Imports are visited after SILFunctions.
llvm::MDModule *Module = MainModule;
swift::Module *M = IGM.Context.getModule(D->getModulePath());
if (!M && D->getModulePath()[0].first.str() == "Builtin")
if (!M &&
D->getModulePath()[0].first == IGM.Context.TheBuiltinModule->getName())
M = IGM.Context.TheBuiltinModule;
if (!M) {
assert(M && "Could not find module for import decl.");
return;
}
auto File = getOrCreateFile(getFilenameFromDC(M->getFiles().front()));
auto DIMod = getOrCreateModule({D->getModulePath(), M});
Location L = getLoc(SM, D);
DBuilder.createImportedModule(getOrCreateFile(L.Filename), DIMod, L.Line);
}
std::string Printed, Mangled("_T");
{
llvm::raw_string_ostream MS(Mangled), PS(Printed);
bool first = true;
for (auto elt : D->getModulePath()) {
llvm::DIModule *
IRGenDebugInfo::getOrCreateModule(ModuleDecl::ImportedModule M) {
const char *fn = getFilenameFromDC(M.second);
StringRef Path(fn ? fn : "");
if (M.first.empty()) {
StringRef Name = M.second->getName().str();
return getOrCreateModule(Name, TheCU, Name, Path);
}
unsigned I = 0;
SmallString<128> AccessPath;
llvm::DIScope *Scope = TheCU;
llvm::raw_svector_ostream OS(AccessPath);
for (auto elt : M.first) {
auto Component = elt.first.str();
// We model each component of the access path as a module.
if (first && Component == D->getASTContext().StdlibModuleName.str())
MS << "S";
else
mangleIdent(MS, Component);
Module = getOrCreateModule(Module, Component, File);
if (first)
first = false;
else
PS << '.';
PS << Component;
if (++I > 1)
OS << '.';
OS << Component;
OS.flush();
Scope = getOrCreateModule(AccessPath, Scope, Component, Path);
}
}
StringRef Name = BumpAllocatedString(Printed);
unsigned Line = getLoc(SM, D).Line;
createImportedModule(Name, Mangled, Module, Line);
}
// Create an imported module and import declarations for all functions
// from that module.
void IRGenDebugInfo::createImportedModule(StringRef Name, StringRef Mangled,
llvm::MDModule *Module,
unsigned Line) {
llvm::SmallString<512> Path(Module->getDirectory());
llvm::sys::path::append(Path, Module->getFilename());
auto File = getOrCreateFile(BumpAllocatedString(Path).data());
DBuilder.createImportedModule(File, Module, Line);
return cast<llvm::DIModule>(Scope);
}
/// Return a cached module for an access path or create a new one.
llvm::MDModule *IRGenDebugInfo::getOrCreateModule(llvm::DIScope *Parent,
std::string Name,
llvm::DIFile *File) {
llvm::DIModule *IRGenDebugInfo::getOrCreateModule(StringRef Key,
llvm::DIScope *Parent,
StringRef Name,
StringRef Filename) {
// Look in the cache first.
auto CachedM = DIModuleCache.find(Name);
auto Val = DIModuleCache.find(Key);
if (Val != DIModuleCache.end())
return cast<llvm::DIModule>(Val->second);
if (CachedM != DIModuleCache.end())
// Verify that the information still exists.
if (llvm::Metadata *Val = CachedM->second)
return cast<llvm::MDModule>(Val);
auto M = DBuilder.createModule(Parent, Name, File, 1);
DIModuleCache[Name] = llvm::TrackingMDNodeRef(M);
StringRef ConfigMacros;
StringRef Sysroot = IGM.Context.SearchPathOpts.SDKPath;
SmallString<256> IncludePath(Filename);
llvm::sys::path::remove_filename(IncludePath);
auto M =
DBuilder.createModule(Parent, Name, ConfigMacros, IncludePath, Sysroot);
DIModuleCache.insert({Key, llvm::TrackingMDNodeRef(M)});
return M;
}
@@ -1538,15 +1498,24 @@ llvm::DIType *IRGenDebugInfo::createType(DebugTypeInfo DbgTy,
L.Filename = ClangSM.getBufferName(ClangSrcLoc);
// Use "ObjectiveC" as default for implicit decls.
// FIXME 1: Do something more clever based on the decl's mangled name.
// FIXME 2: Clang submodules are not handled here.
// FIXME: Do something more clever based on the decl's mangled name.
StringRef ModulePath;
StringRef ModuleName = "ObjectiveC";
if (auto *OwningModule = ClangDecl->getImportedOwningModule())
ModuleName = OwningModule->getTopLevelModuleName();
auto ModuleFile = getOrCreateFile(L.Filename);
// This placeholder gets RAUW'd by finalize().
Scope = getOrCreateModule(ModuleFile, ModuleName, ModuleFile);
if (auto *SwiftModule = Decl->getParentModule())
if (auto *ClangModule = SwiftModule->findUnderlyingClangModule()) {
// FIXME: Clang submodules are not handled here.
// FIXME: Clang module config macros are not handled here.
ModuleName = ClangModule->getFullModuleName();
// FIXME: A clang module's Directory is supposed to be the
// directory containing the module map, but ClangImporter
// sets it to the module cache directory.
if (ClangModule->Directory)
ModulePath = ClangModule->Directory->getName();
}
Scope = getOrCreateModule(ModuleName, TheCU, ModuleName, ModulePath);
}
return createPointerSizedStruct(Scope, Decl->getNameStr(),
getOrCreateFile(L.Filename), L.Line, Flags,

View File

@@ -24,6 +24,7 @@
#include "llvm/IR/DIBuilder.h"
#include "llvm/Support/Allocator.h"
#include "swift/AST/Module.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILBasicBlock.h"
@@ -84,7 +85,7 @@ class IRGenDebugInfo {
llvm::DenseMap<SILDebugScope *, llvm::TrackingMDNodeRef> ScopeCache;
llvm::DenseMap<const char *, llvm::TrackingMDNodeRef> DIFileCache;
llvm::DenseMap<TypeBase *, llvm::TrackingMDNodeRef> DITypeCache;
std::map<std::string, llvm::TrackingMDNodeRef> DIModuleCache;
llvm::StringMap<llvm::TrackingMDNodeRef> DIModuleCache;
TrackingDIRefMap DIRefMap;
llvm::SmallString<256> MainFilename;
@@ -92,7 +93,7 @@ class IRGenDebugInfo {
StringRef CWDName; /// The current working directory.
llvm::DICompileUnit *TheCU = nullptr; /// The current compilation unit.
llvm::DIFile *MainFile = nullptr; /// The main file.
llvm::MDModule *MainModule = nullptr; /// The current module.
llvm::DIModule *MainModule = nullptr; /// The current module.
llvm::MDNode *EntryPointFn; /// Scope of SWIFT_ENTRY_POINT_FUNCTION.
TypeAliasDecl *MetadataTypeDecl; /// The type decl for swift.type.
llvm::DIType *InternalType; /// Catch-all type for opaque internal types.
@@ -247,9 +248,6 @@ private:
StringRef BumpAllocatedString(std::string S);
StringRef BumpAllocatedString(StringRef S);
void createImportedModule(StringRef Name, StringRef MangledPrefix,
llvm::MDModule *Module, unsigned Line);
llvm::DIType *createType(DebugTypeInfo DbgTy, StringRef MangledName,
llvm::DIScope *Scope, llvm::DIFile *File);
llvm::DIType *getOrCreateType(DebugTypeInfo DbgTy);
@@ -275,8 +273,9 @@ private:
DeclContext *DeclContext,
unsigned &SizeInBits);
llvm::DIFile *getFile(llvm::DIScope *Scope);
llvm::MDModule *getOrCreateModule(llvm::DIScope *Parent, std::string Name,
llvm::DIFile *File);
llvm::DIModule *getOrCreateModule(ModuleDecl::ImportedModule M);
llvm::DIModule *getOrCreateModule(StringRef Key, llvm::DIScope *Parent,
StringRef Name, StringRef Filename);
llvm::DIScope *getModule(StringRef MangledName);
llvm::DINodeArray getStructMembers(NominalTypeDecl *D, Type BaseTy,
llvm::DIScope *Scope, llvm::DIFile *File,

View File

@@ -5,15 +5,14 @@
// RUN: %target-swift-frontend -c -module-name Foo %s -I %t -g -o %t.o
// RUN: llvm-dwarfdump %t.o | FileCheck --check-prefix=DWARF %s
// CHECK-DAG: ![[FOOMODULE:[0-9]+]] = !MDModule(name: "Foo"
// CHECK-DAG: ![[FOOMODULE:[0-9]+]] = !DIModule({{.*}}, name: "Foo", includePath: "{{.*}}test{{.*}}DebugInfo{{.*}}", isysroot:
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[THISFILE:[0-9]+]], entity: ![[FOOMODULE]]
// CHECK-DAG: ![[THISFILE]] = !DIFile(filename: "Imports.swift", directory: "{{.*}}test/DebugInfo")
// CHECK-DAG: ![[SWIFTFILE:[0-9]+]] = !DIFile(filename: "Swift.swiftmodule"
// CHECK-DAG: ![[SWIFTMODULE:[0-9]+]] = !MDModule(name: "Swift"
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[SWIFTFILE]], entity: ![[SWIFTMODULE]]
// CHECK-DAG: ![[BASICFILE:[0-9]+]] = !DIFile(filename: "basic.swiftmodule"
// CHECK-DAG: ![[BASICMODULE:[0-9]+]] = !MDModule(name: "basic"
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[BASICFILE]], entity: ![[BASICMODULE]]
// CHECK-DAG: ![[SWIFTMODULE:[0-9]+]] = !DIModule({{.*}}, name: "Swift"
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[THISFILE]], entity: ![[SWIFTMODULE]]
// CHECK-DAG: ![[BASICMODULE:[0-9]+]] = !DIModule({{.*}}, name: "basic"
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[THISFILE]], entity: ![[BASICMODULE]]
import basic
import typealias Swift.Optional
@@ -22,12 +21,16 @@ markUsed(basic.foo(1, 2))
// DWARF: .debug_info
// DWARF: DW_TAG_module
// DWARF-DAG: "Foo"
// DWARF-DAG: "Swift"
// DWARF-DAG: "basic"
// DWARF: DW_AT_name {{.*}}"Swift"
// DWARF: DW_AT_LLVM_include_path
// DWARF: DW_AT_LLVM_isysroot
// DWARF: DW_TAG_module
// DWARF: DW_AT_name {{.*}}"Foo"
// DWARF: DW_AT_LLVM_include_path
// DWARF: DW_AT_LLVM_isysroot
// DWARF: DW_TAG_module
// DWARF: DW_AT_name {{.*}}"basic"
// DWARF-NOT: "Swift.Optional"
// DWARF-DAG: file_names{{.*}} Imports.swift
// DWARF-DAG: file_names{{.*}} Swift.swiftmodule
// DWARF-DAG: file_names{{.*}} basic.swift

View File

@@ -65,14 +65,9 @@ func foo(var a: Int64, var _ b: Int64) -> Int64 {
// Function type for foo.
// CHECK-DAG: ![[FOOTYPE]] = !DISubroutineType(types: ![[PARAMTYPES:[0-9]+]])
// CHECK-DAG: ![[PARAMTYPES]] = !{!"_TtVSs5Int64", !"_TtVSs5Int64", !"_TtVSs5Int64"}
// Import of the main module.
// Import of the main module with the implicit name.
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[MAINFILE]], entity: ![[MAINMODULE:[0-9]+]], line: 1)
// CHECK-DAG: ![[MAINMODULE]] = !MDModule(name: "basic"
// Import of the swift standard library.
// CHECK-DAG: ![[SWIFTFILE:[0-9]+]] = !DIFile(filename: "{{.*}}Swift.swiftmodule",
// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[SWIFTFILE]], entity: ![[SWIFTMODULE:[0-9]+]])
// CHECK-DAG: ![[SWIFTMODULE]] = !MDModule(name: "Swift"
// CHECK-DAG: ![[MAINMODULE]] = !DIModule({{.*}}, name: "basic"
// DWARF Version
// CHECK-DAG: i32 2, !"Dwarf Version", i32 3}

View File

@@ -5,7 +5,7 @@
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Protocol",
// CHECK-SAME: scope: ![[ObjectiveC:[0-9]+]]
// CHECK-SAME: identifier: "_TtCSo8Protocol"
// CHECK: ![[ObjectiveC]] = !MDModule(name: "ObjectiveC"
// CHECK: ![[ObjectiveC]] = !DIModule({{.*}}, name: "ObjectiveC"
import Foundation
public func f() {

View File

@@ -37,10 +37,8 @@ class MyObject : NSObject {
// LOC-CHECK: ret
var MyArr = NSArray()
// IMPORT-CHECK: filename: "test-foundation.swift"
// IMPORT-CHECK: !MDModule(name: "ObjectiveC"
// IMPORT-CHECK: [[FOUNDATION:[0-9]+]] = !MDModule(name: "Foundation",
// IMPORT-CHECK-SAME: {{.*}}file: ![[FOUNDATION_FILE:[0-9]+]]
// IMPORT-CHECK: ![[FOUNDATION_FILE]] = !DIFile(filename: "Foundation-{{.*}}.pcm"
// IMPORT-CHECK: [[FOUNDATION:[0-9]+]] = !DIModule({{.*}} name: "Foundation",
// IMPORT-CHECK-SAME: {{.*}} includePath:
// IMPORT-CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "NSArray",
// IMPORT-CHECK-SAME: scope: ![[FOUNDATION]]
// IMPORT-CHECK: !DIImportedEntity(tag: DW_TAG_imported_module, {{.*}}entity: ![[FOUNDATION]]

View File

@@ -6,7 +6,7 @@ markUsed(a)
// Verify that global variables are emitted once in main, once as
// global variable.
// CHECK: ![[MAIN:.*]] = !DISubprogram(name: "main",{{.*}} line: 1
// CHECK: ![[MOD:.*]] = !MDModule(name: "top_level_var"
// CHECK: ![[MOD:.*]] = !DIModule({{.*}}, name: "top_level_var"
// CHECK: !DIGlobalVariable(name: "a",
// CHECK-SAME: scope: ![[MOD]]
// CHECK-SAME: isDefinition: true

View File

@@ -8,7 +8,7 @@
// Test variables-interpreter.swift runs this code with `swift -g -i`.
// Test variables-repl.swift runs this code with `swift -g < variables.swift`.
// CHECK-DAG: ![[TLC:.*]] = !MDModule(name: "variables"
// CHECK-DAG: ![[TLC:.*]] = !DIModule({{.*}}, name: "variables"
// Global variables.
var glob_i8: Int8 = 8;