aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenAction.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /clang/lib/CodeGen/CodeGenAction.cpp
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'clang/lib/CodeGen/CodeGenAction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp159
1 files changed, 100 insertions, 59 deletions
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 2b219267869e..a3b72381d73f 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/CodeGen/CodeGenAction.h"
+#include "CGCall.h"
#include "CodeGenModule.h"
#include "CoverageMappingGen.h"
#include "MacroPPCallbacks.h"
@@ -86,7 +87,7 @@ namespace clang {
};
static void reportOptRecordError(Error E, DiagnosticsEngine &Diags,
- const CodeGenOptions CodeGenOpts) {
+ const CodeGenOptions &CodeGenOpts) {
handleAllErrors(
std::move(E),
[&](const LLVMRemarkSetupFileError &E) {
@@ -115,6 +116,7 @@ namespace clang {
const LangOptions &LangOpts;
std::unique_ptr<raw_pwrite_stream> AsmOutStream;
ASTContext *Context;
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
Timer LLVMIRGeneration;
unsigned LLVMIRGenerationRefCount;
@@ -147,7 +149,7 @@ namespace clang {
public:
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
- IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts,
@@ -158,10 +160,10 @@ namespace clang {
CoverageSourceInfo *CoverageInfo = nullptr)
: Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
- AsmOutStream(std::move(OS)), Context(nullptr),
+ AsmOutStream(std::move(OS)), Context(nullptr), FS(VFS),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0),
- Gen(CreateLLVMCodeGen(Diags, InFile, std::move(FS), HeaderSearchOpts,
+ Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS), HeaderSearchOpts,
PPOpts, CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)) {
TimerIsEnabled = CodeGenOpts.TimePasses;
@@ -173,7 +175,7 @@ namespace clang {
// 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,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const HeaderSearchOptions &HeaderSearchOpts,
const PreprocessorOptions &PPOpts,
const CodeGenOptions &CodeGenOpts,
@@ -183,10 +185,10 @@ namespace clang {
CoverageSourceInfo *CoverageInfo = nullptr)
: Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
- Context(nullptr),
+ Context(nullptr), FS(VFS),
LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
LLVMIRGenerationRefCount(0),
- Gen(CreateLLVMCodeGen(Diags, "", std::move(FS), HeaderSearchOpts,
+ Gen(CreateLLVMCodeGen(Diags, "", std::move(VFS), HeaderSearchOpts,
PPOpts, CodeGenOpts, C, CoverageInfo)),
LinkModules(std::move(LinkModules)), CurLinkModule(Module) {
TimerIsEnabled = CodeGenOpts.TimePasses;
@@ -261,15 +263,17 @@ namespace clang {
}
// Links each entry in LinkModules into our module. Returns true on error.
- bool LinkInModules() {
+ bool LinkInModules(llvm::Module *M) {
for (auto &LM : LinkModules) {
+ assert(LM.Module && "LinkModule does not actually have a module");
if (LM.PropagateAttrs)
for (Function &F : *LM.Module) {
// Skip intrinsics. Keep consistent with how intrinsics are created
// in LLVM IR.
if (F.isIntrinsic())
continue;
- Gen->CGM().addDefaultFunctionDefinitionAttributes(F);
+ CodeGen::mergeDefaultFunctionDefinitionAttributes(
+ F, CodeGenOpts, LangOpts, TargetOpts, LM.Internalize);
}
CurLinkModule = LM.Module.get();
@@ -277,20 +281,20 @@ namespace clang {
bool Err;
if (LM.Internalize) {
Err = Linker::linkModules(
- *getModule(), std::move(LM.Module), LM.LinkFlags,
+ *M, std::move(LM.Module), LM.LinkFlags,
[](llvm::Module &M, const llvm::StringSet<> &GVS) {
internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
return !GV.hasName() || (GVS.count(GV.getName()) == 0);
});
});
} else {
- Err = Linker::linkModules(*getModule(), std::move(LM.Module),
- LM.LinkFlags);
+ Err = Linker::linkModules(*M, std::move(LM.Module), LM.LinkFlags);
}
if (Err)
return true;
}
+ LinkModules.clear();
return false; // success
}
@@ -353,7 +357,7 @@ namespace clang {
}
// Link each LinkModule into our module.
- if (LinkInModules())
+ if (LinkInModules(getModule()))
return;
for (auto &F : getModule()->functions()) {
@@ -381,7 +385,7 @@ namespace clang {
EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
LangOpts, C.getTargetInfo().getDataLayoutString(),
- getModule(), Action, std::move(AsmOutStream));
+ getModule(), Action, FS, std::move(AsmOutStream));
Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
@@ -631,9 +635,8 @@ BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) {
return false;
Diags.Report(*Loc, diag::warn_fe_frame_larger_than)
- << D.getStackSize()
- << D.getStackLimit()
- << llvm::demangle(D.getFunction().getName().str());
+ << D.getStackSize() << D.getStackLimit()
+ << llvm::demangle(D.getFunction().getName());
return true;
}
@@ -647,7 +650,7 @@ bool BackendConsumer::ResourceLimitDiagHandler(
Diags.Report(*Loc, DiagID)
<< D.getResourceName() << D.getResourceSize() << D.getResourceLimit()
- << llvm::demangle(D.getFunction().getName().str());
+ << llvm::demangle(D.getFunction().getName());
return true;
}
@@ -852,7 +855,7 @@ void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
Diags.Report(LocCookie, D.getSeverity() == DiagnosticSeverity::DS_Error
? diag::err_fe_backend_error_attr
: diag::warn_fe_backend_warning_attr)
- << llvm::demangle(D.getFunctionName().str()) << D.getNote();
+ << llvm::demangle(D.getFunctionName()) << D.getNote();
}
void BackendConsumer::MisExpectDiagHandler(
@@ -990,6 +993,36 @@ CodeGenAction::~CodeGenAction() {
delete VMContext;
}
+bool CodeGenAction::loadLinkModules(CompilerInstance &CI) {
+ if (!LinkModules.empty())
+ return false;
+
+ for (const CodeGenOptions::BitcodeFileToLink &F :
+ CI.getCodeGenOpts().LinkBitcodeFiles) {
+ auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename);
+ if (!BCBuf) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file)
+ << F.Filename << BCBuf.getError().message();
+ LinkModules.clear();
+ return true;
+ }
+
+ Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
+ getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext);
+ if (!ModuleOrErr) {
+ handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
+ CI.getDiagnostics().Report(diag::err_cannot_open_file)
+ << F.Filename << EIB.message();
+ });
+ LinkModules.clear();
+ return true;
+ }
+ LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
+ F.Internalize, F.LinkFlags});
+ }
+ return false;
+}
+
bool CodeGenAction::hasIRSupport() const { return true; }
void CodeGenAction::EndSourceFileAction() {
@@ -1044,33 +1077,9 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (BA != Backend_EmitNothing && !OS)
return nullptr;
- VMContext->setOpaquePointers(CI.getCodeGenOpts().OpaquePointers);
-
// Load bitcode modules to link with, if we need to.
- if (LinkModules.empty())
- for (const CodeGenOptions::BitcodeFileToLink &F :
- CI.getCodeGenOpts().LinkBitcodeFiles) {
- auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename);
- if (!BCBuf) {
- CI.getDiagnostics().Report(diag::err_cannot_open_file)
- << F.Filename << BCBuf.getError().message();
- LinkModules.clear();
- return nullptr;
- }
-
- Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
- getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext);
- if (!ModuleOrErr) {
- handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
- CI.getDiagnostics().Report(diag::err_cannot_open_file)
- << F.Filename << EIB.message();
- });
- LinkModules.clear();
- return nullptr;
- }
- LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
- F.Internalize, F.LinkFlags});
- }
+ if (loadLinkModules(CI))
+ return nullptr;
CoverageSourceInfo *CoverageInfo = nullptr;
// Add the preprocessor callback only when the coverage mapping is generated.
@@ -1103,7 +1112,14 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
CompilerInstance &CI = getCompilerInstance();
SourceManager &SM = CI.getSourceManager();
- VMContext->setOpaquePointers(CI.getCodeGenOpts().OpaquePointers);
+ auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> {
+ unsigned DiagID =
+ CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
+ handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
+ CI.getDiagnostics().Report(DiagID) << EIB.message();
+ });
+ return {};
+ };
// For ThinLTO backend invocations, ensure that the context
// merges types based on ODR identifiers. We also need to read
@@ -1111,15 +1127,6 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
VMContext->enableDebugTypeODRUniquing();
- auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> {
- unsigned DiagID =
- CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
- handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
- CI.getDiagnostics().Report(DiagID) << EIB.message();
- });
- return {};
- };
-
Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef);
if (!BMsOrErr)
return DiagErrors(BMsOrErr.takeError());
@@ -1140,10 +1147,39 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
return std::move(*MOrErr);
}
+ // Load bitcode modules to link with, if we need to.
+ if (loadLinkModules(CI))
+ return nullptr;
+
+ // Handle textual IR and bitcode file with one single module.
llvm::SMDiagnostic Err;
if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext))
return M;
+ // If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
+ // output), place the extra modules (actually only one, a regular LTO module)
+ // into LinkModules as if we are using -mlink-bitcode-file.
+ Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef);
+ if (BMsOrErr && BMsOrErr->size()) {
+ std::unique_ptr<llvm::Module> FirstM;
+ for (auto &BM : *BMsOrErr) {
+ Expected<std::unique_ptr<llvm::Module>> MOrErr =
+ BM.parseModule(*VMContext);
+ if (!MOrErr)
+ return DiagErrors(MOrErr.takeError());
+ if (FirstM)
+ LinkModules.push_back({std::move(*MOrErr), /*PropagateAttrs=*/false,
+ /*Internalize=*/false, /*LinkFlags=*/{}});
+ else
+ FirstM = std::move(*MOrErr);
+ }
+ if (FirstM)
+ return FirstM;
+ }
+ // If BMsOrErr fails, consume the error and use the error message from
+ // parseIR.
+ consumeError(BMsOrErr.takeError());
+
// Translate from the diagnostic info to the SourceManager location if
// available.
// TODO: Unify this with ConvertBackendLocation()
@@ -1219,6 +1255,11 @@ void CodeGenAction::ExecuteAction() {
CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(), TheModule.get(),
std::move(LinkModules), *VMContext, nullptr);
+
+ // Link in each pending link module.
+ if (Result.LinkInModules(&*TheModule))
+ return;
+
// PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be
// true here because the valued names are needed for reading textual IR.
Ctx.setDiscardValueNames(false);
@@ -1238,10 +1279,10 @@ void CodeGenAction::ExecuteAction() {
std::unique_ptr<llvm::ToolOutputFile> OptRecordFile =
std::move(*OptRecordFileOrErr);
- EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts,
- TargetOpts, CI.getLangOpts(),
- CI.getTarget().getDataLayoutString(), TheModule.get(), BA,
- std::move(OS));
+ EmitBackendOutput(
+ Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts, TargetOpts,
+ CI.getLangOpts(), CI.getTarget().getDataLayoutString(), TheModule.get(),
+ BA, CI.getFileManager().getVirtualFileSystemPtr(), std::move(OS));
if (OptRecordFile)
OptRecordFile->keep();
}