Skip to content

Commit 6031fae

Browse files
committed
[CodeGen] Implement post-opt linking option for builtin bitocdes (llvm#69371)
In this patch, we create a new ModulePass that mimics the LinkInModules API from CodeGenAction.cpp, and a new command line option to enable the pass. As part of the implementation, we needed to refactor the BackendConsumer class definition into a new separate header (instead of embedded in CodeGenAction.cpp). With this new pass, we can now re-link bitcodes supplied via the -mlink-built-in bitcodes as part of the RunOptimizationPipeline. With the re-linking pass, we now handle cases where new device library functions are introduced as part of the optimization pipeline. Previously, these newly introduced functions (for example a fused sincos call) would result in a linking error due to a missing function definition. This new pass can be initiated via: -mllvm -relink-builtin-bitcode-postop Also note we intentionally exclude bitcodes supplied via the -mlink-bitcode-file option from the second linking step Change-Id: I77b6e79e69b89feb8ca7c3ac6f792f6881a23129
1 parent f6bf1d7 commit 6031fae

File tree

7 files changed

+592
-401
lines changed

7 files changed

+592
-401
lines changed

clang/include/clang/CodeGen/BackendUtil.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace clang {
3030
class CodeGenOptions;
3131
class TargetOptions;
3232
class LangOptions;
33+
class BackendConsumer;
3334

3435
enum BackendAction {
3536
Backend_EmitAssembly, ///< Emit native assembly files
@@ -45,7 +46,8 @@ namespace clang {
4546
const TargetOptions &TOpts, const LangOptions &LOpts,
4647
StringRef TDesc, llvm::Module *M, BackendAction Action,
4748
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
48-
std::unique_ptr<raw_pwrite_stream> OS);
49+
std::unique_ptr<raw_pwrite_stream> OS,
50+
BackendConsumer *BC = nullptr);
4951

5052
void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
5153
llvm::MemoryBufferRef Buf);

clang/lib/CodeGen/BackendConsumer.h

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
//===--- BackendConsumer.h - LLVM BackendConsumer Header File -------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_LIB_CODEGEN_BACKENDCONSUMER_H
10+
#define LLVM_CLANG_LIB_CODEGEN_BACKENDCONSUMER_H
11+
12+
#include "clang/CodeGen/BackendUtil.h"
13+
#include "clang/CodeGen/CodeGenAction.h"
14+
15+
#include "llvm/IR/DiagnosticInfo.h"
16+
#include "llvm/Support/Timer.h"
17+
18+
namespace llvm {
19+
class DiagnosticInfoDontCall;
20+
}
21+
22+
namespace clang {
23+
class ASTContext;
24+
class CodeGenAction;
25+
class CoverageSourceInfo;
26+
27+
class BackendConsumer : public ASTConsumer {
28+
using LinkModule = CodeGenAction::LinkModule;
29+
30+
virtual void anchor();
31+
DiagnosticsEngine &Diags;
32+
BackendAction Action;
33+
const HeaderSearchOptions &HeaderSearchOpts;
34+
const CodeGenOptions &CodeGenOpts;
35+
const TargetOptions &TargetOpts;
36+
const LangOptions &LangOpts;
37+
std::unique_ptr<raw_pwrite_stream> AsmOutStream;
38+
ASTContext *Context;
39+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
40+
41+
llvm::Timer LLVMIRGeneration;
42+
unsigned LLVMIRGenerationRefCount;
43+
44+
/// True if we've finished generating IR. This prevents us from generating
45+
/// additional LLVM IR after emitting output in HandleTranslationUnit. This
46+
/// can happen when Clang plugins trigger additional AST deserialization.
47+
bool IRGenFinished = false;
48+
49+
bool TimerIsEnabled = false;
50+
51+
std::unique_ptr<CodeGenerator> Gen;
52+
53+
SmallVector<LinkModule, 4> LinkModules;
54+
55+
// A map from mangled names to their function's source location, used for
56+
// backend diagnostics as the Clang AST may be unavailable. We actually use
57+
// the mangled name's hash as the key because mangled names can be very
58+
// long and take up lots of space. Using a hash can cause name collision,
59+
// but that is rare and the consequences are pointing to a wrong source
60+
// location which is not severe. This is a vector instead of an actual map
61+
// because we optimize for time building this map rather than time
62+
// retrieving an entry, as backend diagnostics are uncommon.
63+
std::vector<std::pair<llvm::hash_code, FullSourceLoc>>
64+
ManglingFullSourceLocs;
65+
66+
67+
// This is here so that the diagnostic printer knows the module a diagnostic
68+
// refers to.
69+
llvm::Module *CurLinkModule = nullptr;
70+
71+
public:
72+
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
73+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
74+
const HeaderSearchOptions &HeaderSearchOpts,
75+
const PreprocessorOptions &PPOpts,
76+
const CodeGenOptions &CodeGenOpts,
77+
const TargetOptions &TargetOpts,
78+
const LangOptions &LangOpts, const std::string &InFile,
79+
SmallVector<LinkModule, 4> LinkModules,
80+
std::unique_ptr<raw_pwrite_stream> OS, llvm::LLVMContext &C,
81+
CoverageSourceInfo *CoverageInfo = nullptr);
82+
83+
// This constructor is used in installing an empty BackendConsumer
84+
// to use the clang diagnostic handler for IR input files. It avoids
85+
// initializing the OS field.
86+
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
87+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
88+
const HeaderSearchOptions &HeaderSearchOpts,
89+
const PreprocessorOptions &PPOpts,
90+
const CodeGenOptions &CodeGenOpts,
91+
const TargetOptions &TargetOpts,
92+
const LangOptions &LangOpts, llvm::Module *Module,
93+
SmallVector<LinkModule, 4> LinkModules, llvm::LLVMContext &C,
94+
CoverageSourceInfo *CoverageInfo = nullptr);
95+
96+
llvm::Module *getModule() const;
97+
std::unique_ptr<llvm::Module> takeModule();
98+
99+
CodeGenerator *getCodeGenerator();
100+
101+
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override;
102+
void Initialize(ASTContext &Ctx) override;
103+
bool HandleTopLevelDecl(DeclGroupRef D) override;
104+
void HandleInlineFunctionDefinition(FunctionDecl *D) override;
105+
void HandleInterestingDecl(DeclGroupRef D) override;
106+
void HandleTranslationUnit(ASTContext &C) override;
107+
void HandleTagDeclDefinition(TagDecl *D) override;
108+
void HandleTagDeclRequiredDefinition(const TagDecl *D) override;
109+
void CompleteTentativeDefinition(VarDecl *D) override;
110+
void CompleteExternalDeclaration(VarDecl *D) override;
111+
void AssignInheritanceModel(CXXRecordDecl *RD) override;
112+
void HandleVTable(CXXRecordDecl *RD) override;
113+
114+
115+
// Links each entry in LinkModules into our module. Returns true on error.
116+
bool LinkInModules(llvm::Module *M, bool ShouldLinkFiles = true);
117+
118+
/// Get the best possible source location to represent a diagnostic that
119+
/// may have associated debug info.
120+
const FullSourceLoc getBestLocationFromDebugLoc(
121+
const llvm::DiagnosticInfoWithLocationBase &D,
122+
bool &BadDebugInfo, StringRef &Filename,
123+
unsigned &Line, unsigned &Column) const;
124+
125+
std::optional<FullSourceLoc> getFunctionSourceLocation(
126+
const llvm::Function &F) const;
127+
128+
void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
129+
/// Specialized handler for InlineAsm diagnostic.
130+
/// \return True if the diagnostic has been successfully reported, false
131+
/// otherwise.
132+
bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
133+
/// Specialized handler for diagnostics reported using SMDiagnostic.
134+
void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D);
135+
/// Specialized handler for StackSize diagnostic.
136+
/// \return True if the diagnostic has been successfully reported, false
137+
/// otherwise.
138+
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
139+
/// Specialized handler for ResourceLimit diagnostic.
140+
/// \return True if the diagnostic has been successfully reported, false
141+
/// otherwise.
142+
bool ResourceLimitDiagHandler(const llvm::DiagnosticInfoResourceLimit &D);
143+
144+
/// Specialized handler for unsupported backend feature diagnostic.
145+
void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D);
146+
/// Specialized handlers for optimization remarks.
147+
/// Note that these handlers only accept remarks and they always handle
148+
/// them.
149+
void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
150+
unsigned DiagID);
151+
void
152+
OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D);
153+
void OptimizationRemarkHandler(
154+
const llvm::OptimizationRemarkAnalysisFPCommute &D);
155+
void OptimizationRemarkHandler(
156+
const llvm::OptimizationRemarkAnalysisAliasing &D);
157+
void OptimizationFailureHandler(
158+
const llvm::DiagnosticInfoOptimizationFailure &D);
159+
void DontCallDiagHandler(const llvm::DiagnosticInfoDontCall &D);
160+
/// Specialized handler for misexpect warnings.
161+
/// Note that misexpect remarks are emitted through ORE
162+
void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D);
163+
};
164+
165+
} // namespace clang
166+
#endif

0 commit comments

Comments
 (0)