...instead of calling `llvm::sys::fs::current_path()` directly.
Differential Revision: https://reviews.llvm.org/D130443
#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/LLVM.h"
namespace llvm {
class Constant;
class LLVMContext;
class Module;
class StringRef;
+
+ namespace vfs {
+ class FileSystem;
+ }
}
namespace clang {
/// the allocated CodeGenerator instance.
CodeGenerator *CreateLLVMCodeGen(DiagnosticsEngine &Diags,
llvm::StringRef ModuleName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PreprocessorOpts,
const CodeGenOptions &CGO,
- llvm::LLVMContext& C,
+ llvm::LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr);
} // end namespace clang
if (!CWDName.empty())
return CWDName;
- SmallString<256> CWD;
- llvm::sys::fs::current_path(CWD);
- return CWDName = internString(CWD);
+ llvm::ErrorOr<std::string> CWD =
+ CGM.getFileSystem()->getCurrentWorkingDirectory();
+ if (!CWD)
+ return StringRef();
+ return CWDName = internString(*CWD);
}
void CGDebugInfo::CreateCompileUnit() {
public:
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts,
AsmOutStream(std::move(OS)), Context(nullptr),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0),
- Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
- CodeGenOpts, C, CoverageInfo)),
+ Gen(CreateLLVMCodeGen(Diags, InFile, std::move(FS), HeaderSearchOpts,
+ PPOpts, CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) {
TimerIsEnabled = CodeGenOpts.TimePasses;
llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
// to use the clang diagnostic handler for IR input files. It avoids
// initializing the OS field.
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts,
Context(nullptr),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0),
- Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts,
- CodeGenOpts, C, CoverageInfo)),
+ Gen(CreateLLVMCodeGen(Diags, "", std::move(FS), HeaderSearchOpts,
+ PPOpts, CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)), CurLinkModule(Module) {
TimerIsEnabled = CodeGenOpts.TimePasses;
llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
CI.getPreprocessor());
std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
- BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
- CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
- CI.getLangOpts(), std::string(InFile), std::move(LinkModules),
- std::move(OS), *VMContext, CoverageInfo));
+ BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
+ CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
+ CI.getTargetOpts(), CI.getLangOpts(), std::string(InFile),
+ std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo));
BEConsumer = Result.get();
// Enable generating macro debug info only when debug info is not disabled and
// Set clang diagnostic handler. To do this we need to create a fake
// BackendConsumer.
- BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
- CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
- CI.getTargetOpts(), CI.getLangOpts(), TheModule.get(),
+ BackendConsumer Result(BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
+ CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(),
+ CI.getCodeGenOpts(), CI.getTargetOpts(),
+ CI.getLangOpts(), TheModule.get(),
std::move(LinkModules), *VMContext, nullptr);
// PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be
// true here because the valued names are needed for reading textual IR.
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 CodeGenOptions &CGO, llvm::Module &M,
DiagnosticsEngine &diags,
CoverageSourceInfo *CoverageInfo)
- : Context(C), LangOpts(C.getLangOpts()), HeaderSearchOpts(HSO),
- PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags),
- Target(C.getTargetInfo()), ABI(createCXXABI(*this)),
- VMContext(M.getContext()), Types(*this), VTables(*this),
- SanitizerMD(new SanitizerMetadata(*this)) {
+ : Context(C), LangOpts(C.getLangOpts()), FS(std::move(FS)),
+ HeaderSearchOpts(HSO), PreprocessorOpts(PPO), CodeGenOpts(CGO),
+ TheModule(M), Diags(diags), Target(C.getTargetInfo()),
+ ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this),
+ VTables(*this), SanitizerMD(new SanitizerMetadata(*this)) {
// Initialize the type cache.
llvm::LLVMContext &LLVMContext = M.getContext();
class FunctionType;
class LLVMContext;
class IndexedInstrProfReader;
+
+namespace vfs {
+class FileSystem;
+}
}
namespace clang {
private:
ASTContext &Context;
const LangOptions &LangOpts;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info.
const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
const CodeGenOptions &CodeGenOpts;
llvm::DenseMap<const llvm::Constant *, llvm::GlobalVariable *> RTTIProxyMap;
public:
- CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts,
+ CodeGenModule(ASTContext &C, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ const HeaderSearchOptions &headersearchopts,
const PreprocessorOptions &ppopts,
const CodeGenOptions &CodeGenOpts, llvm::Module &M,
DiagnosticsEngine &Diags,
ASTContext &getContext() const { return Context; }
const LangOptions &getLangOpts() const { return LangOpts; }
+ const IntrusiveRefCntPtr<llvm::vfs::FileSystem> &getFileSystem() const {
+ return FS;
+ }
const HeaderSearchOptions &getHeaderSearchOpts()
const { return HeaderSearchOpts; }
const PreprocessorOptions &getPreprocessorOpts()
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include <memory>
using namespace clang;
class CodeGeneratorImpl : public CodeGenerator {
DiagnosticsEngine &Diags;
ASTContext *Ctx;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; // Only used for debug info.
const HeaderSearchOptions &HeaderSearchOpts; // Only used for debug info.
const PreprocessorOptions &PreprocessorOpts; // Only used for debug info.
const CodeGenOptions CodeGenOpts; // Intentionally copied in.
public:
CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
const HeaderSearchOptions &HSO,
const PreprocessorOptions &PPO, const CodeGenOptions &CGO,
llvm::LLVMContext &C,
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),
CoverageInfo(CoverageInfo),
M(new llvm::Module(ExpandModuleName(ModuleName, CGO), C)) {
if (auto TVSDKVersion =
Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion())
M->setDarwinTargetVariantSDKVersion(*TVSDKVersion);
- Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts,
+ Builder.reset(new CodeGen::CodeGenModule(Context, FS, HeaderSearchOpts,
PreprocessorOpts, CodeGenOpts,
*M, Diags, CoverageInfo));
return static_cast<CodeGeneratorImpl*>(this)->StartModule(ModuleName, C);
}
-CodeGenerator *clang::CreateLLVMCodeGen(
- DiagnosticsEngine &Diags, llvm::StringRef ModuleName,
- const HeaderSearchOptions &HeaderSearchOpts,
- const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO,
- llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo) {
- return new CodeGeneratorImpl(Diags, ModuleName, HeaderSearchOpts,
- PreprocessorOpts, CGO, C, CoverageInfo);
+CodeGenerator *
+clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, llvm::StringRef ModuleName,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ const HeaderSearchOptions &HeaderSearchOpts,
+ const PreprocessorOptions &PreprocessorOpts,
+ const CodeGenOptions &CGO, llvm::LLVMContext &C,
+ CoverageSourceInfo *CoverageInfo) {
+ return new CodeGeneratorImpl(Diags, ModuleName, std::move(FS),
+ HeaderSearchOpts, PreprocessorOpts, CGO, C,
+ CoverageInfo);
}
const std::string OutputFileName;
ASTContext *Ctx;
ModuleMap &MMap;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
const HeaderSearchOptions &HeaderSearchOpts;
const PreprocessorOptions &PreprocessorOpts;
CodeGenOptions CodeGenOpts;
: Diags(CI.getDiagnostics()), MainFileName(MainFileName),
OutputFileName(OutputFileName), Ctx(nullptr),
MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
+ FS(&CI.getVirtualFileSystem()),
HeaderSearchOpts(CI.getHeaderSearchOpts()),
PreprocessorOpts(CI.getPreprocessorOpts()),
TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()),
M.reset(new llvm::Module(MainFileName, *VMContext));
M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
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.
auto *DI = Builder->getModuleDebugInfo();
llvm::LLVMContext &LLVMCtx) {
StringRef ModuleName("$__module");
return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen(
- CI.getDiagnostics(), ModuleName, CI.getHeaderSearchOpts(),
- CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx));
+ CI.getDiagnostics(), ModuleName, &CI.getVirtualFileSystem(),
+ CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
+ LLVMCtx));
}
} // namespace init_convenience
compiler.createASTContext();
- CG.reset(CreateLLVMCodeGen(compiler.getDiagnostics(),
- "main-module",
- compiler.getHeaderSearchOpts(),
- compiler.getPreprocessorOpts(),
- compiler.getCodeGenOpts(),
- Context));
+ CG.reset(CreateLLVMCodeGen(
+ compiler.getDiagnostics(), "main-module",
+ &compiler.getVirtualFileSystem(), compiler.getHeaderSearchOpts(),
+ compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context));
}
void init(const char *TestProgram,
#include "clang/CodeGen/BackendUtil.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/Support/FormatVariadic.h"
#include "gtest/gtest.h"
using namespace llvm;
bool Success = Compiler.ExecuteAction(Action);
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"));
+}
}