|
34 | 34 | #include "ir/irfuncty.h" |
35 | 35 | #include "ir/irmodule.h" |
36 | 36 | #include "ir/irtypeaggr.h" |
| 37 | +#include "llvm/ADT/DenseMap.h" |
37 | 38 | #include "llvm/ADT/SmallString.h" |
38 | 39 | #include "llvm/Support/FileSystem.h" |
39 | 40 | #include "llvm/Support/Path.h" |
@@ -218,27 +219,71 @@ void DIBuilder::SetValue(Loc loc, llvm::Value *value, |
218 | 219 | IR->scopebb()); |
219 | 220 | } |
220 | 221 |
|
| 222 | +std::string DIBuilder::remapDIPath(llvm::StringRef path) { |
| 223 | + llvm::SmallString<256> P = path; |
| 224 | + for (auto &[from, to] : llvm::reverse(opts::debugPrefixMap)) |
| 225 | + if (llvm::sys::path::replace_path_prefix(P, from, to)) |
| 226 | + break; |
| 227 | + return P.str().str(); |
| 228 | +} |
| 229 | + |
221 | 230 | DIFile DIBuilder::CreateFile(const char *filename) { |
222 | 231 | if (!filename) |
223 | 232 | filename = IR->dmodule->srcfile.toChars(); |
224 | 233 |
|
225 | | - // clang appears to use the curent working dir as 'directory' for relative |
226 | | - // source paths, and the root path for absolute ones: |
227 | | - // clang -g -emit-llvm -S ..\blub.c => |
228 | | - // !DIFile(filename: "..\\blub.c", directory: "C:\\LDC\\ninja-ldc", ...) |
229 | | - // !DIFile(filename: "Program |
230 | | - // Files\\LLVM\\lib\\clang\\11.0.1\\include\\stddef.h", directory: "C:\\", |
231 | | - // ...) |
232 | | - |
233 | | - if (llvm::sys::path::is_absolute(filename)) { |
234 | | - return DBuilder.createFile(llvm::sys::path::relative_path(filename), |
235 | | - llvm::sys::path::root_path(filename)); |
| 234 | + // Mimic clang's behavior as much as possible, including fdebug-prefix-map |
| 235 | + // remap behavior. See LLVM source clang/lib/CodeGen/CGDebugInfo.cpp |
| 236 | + |
| 237 | + // First check cache |
| 238 | + auto iter = filenameToDIFileCache.find(filename); |
| 239 | + if (iter != filenameToDIFileCache.end()) { |
| 240 | + // Verify that the information still exists. |
| 241 | + if (llvm::Metadata *value = iter->second) |
| 242 | + return llvm::cast<llvm::DIFile>(value); |
236 | 243 | } |
237 | 244 |
|
| 245 | + // Cache miss, create a new DIFile |
| 246 | + |
| 247 | + auto remappedFile = remapDIPath(filename); |
| 248 | + |
238 | 249 | llvm::SmallString<128> cwd; |
239 | 250 | llvm::sys::fs::current_path(cwd); |
| 251 | + auto currentDir = remapDIPath(cwd); |
| 252 | + |
| 253 | + llvm::StringRef debuginfoDir; |
| 254 | + llvm::StringRef debuginfoFile; |
| 255 | + |
| 256 | + llvm::SmallString<128> DirBuf; |
| 257 | + llvm::SmallString<128> FileBuf; |
| 258 | + if (llvm::sys::path::is_absolute(remappedFile)) { |
| 259 | + // Strip the common prefix (if it is more than just "/" or "C:\") from |
| 260 | + // current directory and filename for a more space-efficient encoding. |
| 261 | + auto FileIt = llvm::sys::path::begin(remappedFile); |
| 262 | + auto FileE = llvm::sys::path::end(remappedFile); |
| 263 | + auto CurDirIt = llvm::sys::path::begin(currentDir); |
| 264 | + auto CurDirE = llvm::sys::path::end(currentDir); |
| 265 | + for (; CurDirIt != CurDirE && *CurDirIt == *FileIt; ++CurDirIt, ++FileIt) |
| 266 | + llvm::sys::path::append(DirBuf, *CurDirIt); |
| 267 | + if (llvm::sys::path::root_path(DirBuf) == DirBuf) { |
| 268 | + // Don't strip the common prefix if it is only the root ("/" or "C:\") |
| 269 | + // since that would make diagnostic locations confusing. |
| 270 | + debuginfoDir = {}; |
| 271 | + debuginfoFile = remappedFile; |
| 272 | + } else { |
| 273 | + for (; FileIt != FileE; ++FileIt) |
| 274 | + llvm::sys::path::append(FileBuf, *FileIt); |
| 275 | + debuginfoDir = DirBuf; |
| 276 | + debuginfoFile = FileBuf; |
| 277 | + } |
| 278 | + } else { |
| 279 | + if (!llvm::sys::path::is_absolute(filename)) |
| 280 | + debuginfoDir = currentDir; |
| 281 | + debuginfoFile = remappedFile; |
| 282 | + } |
240 | 283 |
|
241 | | - return DBuilder.createFile(filename, cwd); |
| 284 | + auto difile = DBuilder.createFile(debuginfoFile, debuginfoDir); |
| 285 | + filenameToDIFileCache[filename].reset(difile); |
| 286 | + return difile; |
242 | 287 | } |
243 | 288 |
|
244 | 289 | DIFile DIBuilder::CreateFile(Loc loc) { |
|
0 commit comments