[CGDebugInfo] Access the current working directory from the `VFS`

...instead of calling `llvm::sys::fs::current_path()` directly.

Differential Revision: https://reviews.llvm.org/D130443
This commit is contained in:
Argyrios Kyrtzidis 2022-07-23 00:11:44 -07:00
parent 0734c02b34
commit 8dfaecc4c2
10 changed files with 106 additions and 40 deletions

View File

@ -14,12 +14,17 @@
#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H #define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTConsumer.h"
#include "clang/Basic/LLVM.h"
namespace llvm { namespace llvm {
class Constant; class Constant;
class LLVMContext; class LLVMContext;
class Module; class Module;
class StringRef; class StringRef;
namespace vfs {
class FileSystem;
}
} }
namespace clang { namespace clang {
@ -98,10 +103,11 @@ public:
/// the allocated CodeGenerator instance. /// the allocated CodeGenerator instance.
CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags, CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags,
llvm::StringRef ModuleName, llvm::StringRef ModuleName,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HeaderSearchOpts, const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PreprocessorOpts, const PreprocessorOptions &PreprocessorOpts,
const CodeGenOptions &CGO, const CodeGenOptions &CGO,
llvm::LLVMContext& C, llvm::LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr); CoverageSourceInfo *CoverageInfo = nullptr);
} // end namespace clang } // end namespace clang

View File

@ -491,9 +491,11 @@ StringRef CGDebugInfo::getCurrentDirname() {
if (!CWDName.empty()) if (!CWDName.empty())
return CWDName; return CWDName;
SmallString<256> CWD; llvm::ErrorOr<std::string> CWD =
llvm::sys::fs::current_path(CWD); CGM.getFileSystem()->getCurrentWorkingDirectory();
return CWDName = internString(CWD); if (!CWD)
return StringRef();
return CWDName = internString(*CWD);
} }
void CGDebugInfo::CreateCompileUnit() { void CGDebugInfo::CreateCompileUnit() {

View File

@ -146,6 +146,7 @@ namespace clang {
public: public:
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HeaderSearchOpts, const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts, const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts, const CodeGenOptions &CodeGenOpts,
@ -159,8 +160,8 @@ namespace clang {
AsmOutStream(std::move(OS)), Context(nullptr), AsmOutStream(std::move(OS)), Context(nullptr),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0), LLVMIRGenerationRefCount(0),
Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, Gen(CreateLLVMCodeGen(Diags, InFile, std::move(FS), HeaderSearchOpts,
CodeGenOpts, C, CoverageInfo)), PPOpts, CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) { LinkModules(std::move(LinkModules)) {
TimerIsEnabled = CodeGenOpts.TimePasses; TimerIsEnabled = CodeGenOpts.TimePasses;
llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
@ -171,6 +172,7 @@ namespace clang {
// to use the clang diagnostic handler for IR input files. It avoids // to use the clang diagnostic handler for IR input files. It avoids
// initializing the OS field. // initializing the OS field.
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HeaderSearchOpts, const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts, const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts, const CodeGenOptions &CodeGenOpts,
@ -183,8 +185,8 @@ namespace clang {
Context(nullptr), Context(nullptr),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"), LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0), LLVMIRGenerationRefCount(0),
Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, Gen(CreateLLVMCodeGen(Diags, "", std::move(FS), HeaderSearchOpts,
CodeGenOpts, C, CoverageInfo)), PPOpts, CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)), CurLinkModule(Module) { LinkModules(std::move(LinkModules)), CurLinkModule(Module) {
TimerIsEnabled = CodeGenOpts.TimePasses; TimerIsEnabled = CodeGenOpts.TimePasses;
llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
@ -1052,10 +1054,10 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
CI.getPreprocessor()); CI.getPreprocessor());
std::unique_ptr<BackendConsumer> Result(new BackendConsumer( std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
CI.getLangOpts(), std::string(InFile), std::move(LinkModules), CI.getTargetOpts(), CI.getLangOpts(), std::string(InFile),
std::move(OS), *VMContext, CoverageInfo)); std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo));
BEConsumer = Result.get(); BEConsumer = Result.get();
// Enable generating macro debug info only when debug info is not disabled and // Enable generating macro debug info only when debug info is not disabled and
@ -1185,9 +1187,10 @@ void CodeGenAction::ExecuteAction() {
// Set clang diagnostic handler. To do this we need to create a fake // Set clang diagnostic handler. To do this we need to create a fake
// BackendConsumer. // BackendConsumer.
BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), BackendConsumer Result(BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(),
CI.getTargetOpts(), CI.getLangOpts(), TheModule.get(), CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(), TheModule.get(),
std::move(LinkModules), *VMContext, nullptr); std::move(LinkModules), *VMContext, nullptr);
// PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be
// true here because the valued names are needed for reading textual IR. // true here because the valued names are needed for reading textual IR.

View File

@ -96,16 +96,18 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
llvm_unreachable("invalid C++ ABI kind"); llvm_unreachable("invalid C++ ABI kind");
} }
CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, CodeGenModule::CodeGenModule(ASTContext &C,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HSO,
const PreprocessorOptions &PPO, const PreprocessorOptions &PPO,
const CodeGenOptions &CGO, llvm::Module &M, const CodeGenOptions &CGO, llvm::Module &M,
DiagnosticsEngine &diags, DiagnosticsEngine &diags,
CoverageSourceInfo *CoverageInfo) CoverageSourceInfo *CoverageInfo)
: Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO), : Context(C), LangOpts(C.getLangOpts()), FS(std::move(FS)),
PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO),
Target(C.getTargetInfo()), ABI(createCXXABI(*this)), TheModule(M), Diags(diags), Target(C.getTargetInfo()),
VMContext(M.getContext()), Types(*this), VTables(*this), ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this),
SanitizerMD(new SanitizerMetadata(*this)) { VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) {
// Initialize the type cache. // Initialize the type cache.
llvm::LLVMContext &LLVMContext = M.getContext(); llvm::LLVMContext &LLVMContext = M.getContext();

View File

@ -47,6 +47,10 @@ class DataLayout;
class FunctionType; class FunctionType;
class LLVMContext; class LLVMContext;
class IndexedInstrProfReader; class IndexedInstrProfReader;
namespace vfs {
class FileSystem;
}
} }
namespace clang { namespace clang {
@ -293,6 +297,7 @@ public:
private: private:
ASTContext &Context; ASTContext &Context;
const LangOptions &LangOpts; const LangOptions &LangOpts;
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info.
const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
const CodeGenOptions &CodeGenOpts; const CodeGenOptions &CodeGenOpts;
@ -584,7 +589,8 @@ private:
llvm::DenseMap<const llvm::Constant *, llvm::GlobalVariable *> RTTIProxyMap; llvm::DenseMap<const llvm::Constant *, llvm::GlobalVariable *> RTTIProxyMap;
public: public:
CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, CodeGenModule(ASTContext &C, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &headersearchopts,
const PreprocessorOptions &ppopts, const PreprocessorOptions &ppopts,
const CodeGenOptions &CodeGenOpts, llvm::Module &M, const CodeGenOptions &CodeGenOpts, llvm::Module &M,
DiagnosticsEngine &Diags, DiagnosticsEngine &Diags,
@ -712,6 +718,9 @@ public:
ASTContext &getContext() const { return Context; } ASTContext &getContext() const { return Context; }
const LangOptions &getLangOpts() const { return LangOpts; } const LangOptions &getLangOpts() const { return LangOpts; }
const IntrusiveRefCntPtr<llvm::vfs::FileSystem> &getFileSystem() const {
return FS;
}
const HeaderSearchOptions &getHeaderSearchOpts() const HeaderSearchOptions &getHeaderSearchOpts()
const { return HeaderSearchOpts; } const { return HeaderSearchOpts; }
const PreprocessorOptions &getPreprocessorOpts() const PreprocessorOptions &getPreprocessorOpts()

View File

@ -23,6 +23,7 @@
#include "llvm/IR/DataLayout.h" #include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <memory> #include <memory>
using namespace clang; using namespace clang;
@ -32,6 +33,7 @@ namespace {
class CodeGeneratorImpl : public CodeGenerator { class CodeGeneratorImpl : public CodeGenerator {
DiagnosticsEngine &Diags; DiagnosticsEngine &Diags;
ASTContext *Ctx; ASTContext *Ctx;
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info.
const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info. const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
const PreprocessorOptions &PreprocessorOpts; // Only used for debug info. const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
const CodeGenOptions CodeGenOpts; // Intentionally copied in. const CodeGenOptions CodeGenOpts; // Intentionally copied in.
@ -74,11 +76,12 @@ namespace {
public: public:
CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName, CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HSO, const HeaderSearchOptions &HSO,
const PreprocessorOptions &PPO, const CodeGenOptions &CGO, const PreprocessorOptions &PPO, const CodeGenOptions &CGO,
llvm::LLVMContext &C, llvm::LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr) CoverageSourceInfo *CoverageInfo = nullptr)
: Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), : Diags(diags), Ctx(nullptr), FS(std::move(FS)), HeaderSearchOpts(HSO),
PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0), PreprocessorOpts(PPO), CodeGenOpts(CGO), HandlingTopLevelDecls(0),
CoverageInfo(CoverageInfo), CoverageInfo(CoverageInfo),
M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) { M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) {
@ -158,7 +161,7 @@ namespace {
if (auto TVSDKVersion = if (auto TVSDKVersion =
Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion()) Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion())
M->setDarwinTargetVariantSDKVersion(*TVSDKVersion); M->setDarwinTargetVariantSDKVersion(*TVSDKVersion);
Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, Builder.reset(new CodeGen::CodeGenModule(Context, FS, HeaderSearchOpts,
PreprocessorOpts, CodeGenOpts, PreprocessorOpts, CodeGenOpts,
*M, Diags, CoverageInfo)); *M, Diags, CoverageInfo));
@ -356,11 +359,14 @@ llvm::Module *CodeGenerator::StartModule(llvm::StringRef ModuleName,
return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C); return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C);
} }
CodeGenerator *clang::CreateLLVMCodeGen( CodeGenerator *
DiagnosticsEngine &Diags, llvm::StringRef ModuleName, clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName,
const HeaderSearchOptions &HeaderSearchOpts, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, const HeaderSearchOptions &HeaderSearchOpts,
llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) { const PreprocessorOptions &PreprocessorOpts,
return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts, const CodeGenOptions &CGO, llvm::LLVMContext &C,
PreprocessorOpts, CGO, C, CoverageInfo); CoverageSourceInfo *CoverageInfo) {
return new CodeGeneratorImpl(Diags, ModuleName, std::move(FS),
HeaderSearchOpts, PreprocessorOpts, CGO, C,
CoverageInfo);
} }

View File

@ -45,6 +45,7 @@ class PCHContainerGenerator : public ASTConsumer {
const std::string OutputFileName; const std::string OutputFileName;
ASTContext *Ctx; ASTContext *Ctx;
ModuleMap &MMap; ModuleMap &MMap;
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
const HeaderSearchOptions &HeaderSearchOpts; const HeaderSearchOptions &HeaderSearchOpts;
const PreprocessorOptions &PreprocessorOpts; const PreprocessorOptions &PreprocessorOpts;
CodeGenOptions CodeGenOpts; CodeGenOptions CodeGenOpts;
@ -144,6 +145,7 @@ public:
: Diags(CI.getDiagnostics()), MainFileName(MainFileName), : Diags(CI.getDiagnostics()), MainFileName(MainFileName),
OutputFileName(OutputFileName), Ctx(nullptr), OutputFileName(OutputFileName), Ctx(nullptr),
MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
FS(&CI.getVirtualFileSystem()),
HeaderSearchOpts(CI.getHeaderSearchOpts()), HeaderSearchOpts(CI.getHeaderSearchOpts()),
PreprocessorOpts(CI.getPreprocessorOpts()), PreprocessorOpts(CI.getPreprocessorOpts()),
TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
@ -173,7 +175,7 @@ public:
M.reset(new llvm::Module(MainFileName, *VMContext)); M.reset(new llvm::Module(MainFileName, *VMContext));
M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString()); M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
Builder.reset(new CodeGen::CodeGenModule( Builder.reset(new CodeGen::CodeGenModule(
*Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags)); *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
// Prepare CGDebugInfo to emit debug info for a clang module. // Prepare CGDebugInfo to emit debug info for a clang module.
auto *DI = Builder->getModuleDebugInfo(); auto *DI = Builder->getModuleDebugInfo();

View File

@ -230,8 +230,9 @@ std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI,
llvm::LLVMContext &LLVMCtx) { llvm::LLVMContext &LLVMCtx) {
StringRef ModuleName("$__module"); StringRef ModuleName("$__module");
return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen( return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen(
CI.getDiagnostics(), ModuleName, CI.getHeaderSearchOpts(), CI.getDiagnostics(), ModuleName, &CI.getVirtualFileSystem(),
CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx)); CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
LLVMCtx));
} }
} // namespace init_convenience } // namespace init_convenience

View File

@ -56,12 +56,10 @@ struct TestCompiler {
compiler.createASTContext(); compiler.createASTContext();
CG.reset(CreateLLVMCodeGen(compiler.getDiagnostics(), CG.reset(CreateLLVMCodeGen(
"main-module", compiler.getDiagnostics(), "main-module",
compiler.getHeaderSearchOpts(), &compiler.getVirtualFileSystem(), compiler.getHeaderSearchOpts(),
compiler.getPreprocessorOpts(), compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context));
compiler.getCodeGenOpts(),
Context));
} }
void init(const char *TestProgram, void init(const char *TestProgram,

View File

@ -15,6 +15,7 @@
#include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/BackendUtil.h"
#include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Support/FormatVariadic.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
using namespace llvm; using namespace llvm;
@ -76,4 +77,40 @@ TEST(CodeGenTest, CodeGenFromIRMemBuffer) {
bool Success = Compiler.ExecuteAction(Action); bool Success = Compiler.ExecuteAction(Action);
EXPECT_TRUE(Success); EXPECT_TRUE(Success);
} }
TEST(CodeGenTest, DebugInfoCWDCodeGen) {
// Check that debug info is accessing the current working directory from the
// VFS instead of calling \p llvm::sys::fs::current_path() directly.
auto VFS = std::make_unique<llvm::vfs::InMemoryFileSystem>();
VFS->setCurrentWorkingDirectory("/in-memory-fs-cwd");
auto Sept = llvm::sys::path::get_separator();
std::string TestPath =
std::string(llvm::formatv("{0}in-memory-fs-cwd{0}test.cpp", Sept));
VFS->addFile(TestPath, 0, llvm::MemoryBuffer::getMemBuffer("int x;\n"));
auto Invocation = std::make_shared<CompilerInvocation>();
Invocation->getFrontendOpts().Inputs.push_back(
FrontendInputFile("test.cpp", Language::CXX));
Invocation->getFrontendOpts().ProgramAction = EmitLLVM;
Invocation->getTargetOpts().Triple = "x86_64-unknown-linux-gnu";
Invocation->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo);
CompilerInstance Compiler;
SmallString<256> IRBuffer;
Compiler.setOutputStream(std::make_unique<raw_svector_ostream>(IRBuffer));
Compiler.setInvocation(std::move(Invocation));
Compiler.createDiagnostics();
Compiler.createFileManager(std::move(VFS));
EmitLLVMAction Action;
bool Success = Compiler.ExecuteAction(Action);
EXPECT_TRUE(Success);
SmallString<128> RealCWD;
llvm::sys::fs::current_path(RealCWD);
EXPECT_TRUE(!RealCWD.empty());
EXPECT_FALSE(IRBuffer.str().contains(RealCWD));
EXPECT_TRUE(IRBuffer.str().contains("in-memory-fs-cwd"));
}
} }