23#include "llvm/ADT/StringRef.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DataLayout.h"
26#include "llvm/IR/LLVMContext.h"
27#include "llvm/IR/Module.h"
28#include "llvm/MC/TargetRegistry.h"
29#include "llvm/Object/COFF.h"
30#include "llvm/Support/Path.h"
36#define DEBUG_TYPE "pchcontainer"
41 const std::string MainFileName;
42 const std::string OutputFileName;
51 std::unique_ptr<llvm::LLVMContext> VMContext;
52 std::unique_ptr<llvm::Module> M;
53 std::unique_ptr<CodeGen::CodeGenModule> Builder;
54 std::unique_ptr<raw_pwrite_stream> OS;
55 std::shared_ptr<PCHBuffer> Buffer;
65 static bool CanRepresent(
const Type *Ty) {
79 if (
auto *TD = dyn_cast<TagDecl>(
D))
80 if (!TD->isCompleteDefinition())
98 if (isa<CXXDeductionGuideDecl>(
D))
101 if (isa<CXXMethodDecl>(
D))
107 for (
auto *i :
D->parameters())
108 ArgTypes.push_back(i->getType());
118 if (!
D->getClassInterface())
121 bool selfIsPseudoStrong, selfIsConsumed;
123 ArgTypes.push_back(
D->getSelfType(Ctx,
D->getClassInterface(),
124 selfIsPseudoStrong, selfIsConsumed));
126 for (
auto *i :
D->parameters())
127 ArgTypes.push_back(i->getType());
138 PCHContainerGenerator(
CompilerInstance &CI,
const std::string &MainFileName,
139 const std::string &OutputFileName,
140 std::unique_ptr<raw_pwrite_stream> OS,
141 std::shared_ptr<PCHBuffer> Buffer)
143 OutputFileName(OutputFileName), Ctx(
nullptr),
149 OS(std::move(OS)), Buffer(std::move(Buffer)) {
153 LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single);
154 CodeGenOpts.DebugTypeExtRefs =
true;
158 CodeGenOpts.setDebugInfo(llvm::codegenoptions::FullDebugInfo);
159 CodeGenOpts.setDebuggerTuning(CI.
getCodeGenOpts().getDebuggerTuning());
165 CodeGenOpts.DebugStrictDwarf = CI.
getCodeGenOpts().DebugStrictDwarf;
168 ~PCHContainerGenerator()
override =
default;
171 assert(!Ctx &&
"initialized multiple times");
174 VMContext.reset(
new llvm::LLVMContext());
175 M.reset(
new llvm::Module(MainFileName, *VMContext));
178 *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
181 auto *DI = Builder->getModuleDebugInfo();
182 StringRef ModuleName = llvm::sys::path::filename(MainFileName);
183 DI->setPCHDescriptor(
185 DI->setModuleMap(MMap);
194 if (!I->isFromASTFile()) {
195 DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
213 if (
D->getName().empty())
219 if (
auto *
D = dyn_cast<TagDecl>(DeclCtx))
220 if (!
D->isCompleteDefinition())
225 DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
227 Builder->UpdateCompletedType(
D);
234 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D))
235 Builder->getModuleDebugInfo()->completeRequiredType(RD);
240 Builder->getModuleDebugInfo()->EmitImportDecl(*
D);
245 assert(M && VMContext && Builder);
247 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
248 std::unique_ptr<llvm::Module> M = std::move(this->M);
249 std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
262 Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL;
264 Builder->getModuleDebugInfo()->setDwoId(Signature);
273 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error))
274 llvm::report_fatal_error(llvm::Twine(Error));
277 assert(Buffer->IsComplete &&
"serialization did not complete");
278 auto &SerializedAST = Buffer->Data;
279 auto Size = SerializedAST.size();
281 if (Triple.isOSBinFormatWasm()) {
287 llvm::NamedMDNode *MD =
288 M->getOrInsertNamedMetadata(
"wasm.custom_sections");
289 llvm::Metadata *Ops[2] = {
290 llvm::MDString::get(*VMContext,
"__clangast"),
291 llvm::MDString::get(*VMContext,
292 StringRef(SerializedAST.data(), Size))};
293 auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops);
294 MD->addOperand(NameAndContent);
296 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
297 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
298 auto *
Data = llvm::ConstantDataArray::getString(
299 *VMContext, StringRef(SerializedAST.data(), Size),
301 auto *ASTSym =
new llvm::GlobalVariable(
302 *M, Ty,
true, llvm::GlobalVariable::InternalLinkage,
303 Data,
"__clang_ast");
305 ASTSym->setAlignment(llvm::Align(8));
308 if (Triple.isOSBinFormatMachO())
309 ASTSym->setSection(
"__CLANG,__clangast");
311 else if (Triple.isOSBinFormatCOFF())
312 ASTSym->setSection(
"clangast");
314 ASTSym->setSection(
"__clangast");
321 Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
323 BackendAction::Backend_EmitLL, FS,
324 std::make_unique<llvm::raw_svector_ostream>(Buffer));
325 llvm::dbgs() << Buffer;
332 BackendAction::Backend_EmitObj, FS, std::move(OS));
336 SerializedAST = std::move(
Empty);
342std::unique_ptr<ASTConsumer>
343ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
345 const std::string &OutputFileName,
346 std::unique_ptr<llvm::raw_pwrite_stream> OS,
347 std::shared_ptr<PCHBuffer> Buffer)
const {
348 return std::make_unique<PCHContainerGenerator>(
349 CI, MainFileName, OutputFileName, std::move(OS), Buffer);
Defines the clang::ASTContext interface.
Defines the Diagnostic-related interfaces.
Defines the clang::Preprocessor interface.
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
virtual void HandleTagDeclDefinition(TagDecl *D)
HandleTagDeclDefinition - This callback is invoked each time a TagDecl (e.g.
virtual void HandleTranslationUnit(ASTContext &Ctx)
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
virtual void HandleTagDeclRequiredDefinition(const TagDecl *D)
This callback is invoked the first time each TagDecl is required to be complete.
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D)
Handle the specified top-level declaration that occurred inside and ObjC container.
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
virtual void Initialize(ASTContext &Context)
Initialize - This is called to initialize the consumer, providing the ASTContext.
virtual void HandleImplicitImportDecl(ImportDecl *D)
Handle an ImportDecl that was implicitly created due to an inclusion directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
llvm::SmallVector< std::pair< std::string, std::string >, 0 > DebugPrefixMap
std::string CodeModel
The code model to use (-mcmodel).
std::string DebugCompilationDir
The string to embed in debug information as the current working directory.
std::string MainFileName
The user provided name for the "main file", if non-empty.
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
llvm::DIType * getOrCreateStandaloneType(QualType Ty, SourceLocation Loc)
Emit standalone debug info for a type.
void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType, llvm::Function *Fn=nullptr)
Emit debug info for a function declaration.
void EmitImportDecl(const ImportDecl &ID)
Emit an @import declaration.
This class organizes the cross-function state that is used while generating LLVM code.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
TargetOptions & getTargetOpts()
HeaderSearchOptions & getHeaderSearchOpts()
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
llvm::vfs::FileSystem & getVirtualFileSystem() const
LangOptions & getLangOpts()
CodeGenOptions & getCodeGenOpts()
CodeGenOptions & getCodeGenOpts()
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Module * getImportedOwningModule() const
Get the imported owning module, if this decl is from an imported (non-local) module.
bool isFromASTFile() const
Determine whether this declaration came from an AST file (such as a precompiled header or module) rat...
SourceLocation getLocation() const
DeclContext * getDeclContext()
Concrete class used by the front-end to report problems and issues.
bool hasErrorOccurred() const
Represents a function declaration or definition.
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::string CurrentModule
The name of the current module, of which the main source file is a part.
Represents an ObjC class declaration.
ObjCMethodDecl - Represents an instance or class method declaration.
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
HeaderSearch & getHeaderSearchInfo() const
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Represents a struct/union/class.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Represents the declaration of a struct/union/class/enum.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
const char * getDataLayoutString() const
Options for controlling the target.
Represents a declaration of a type.
The base class of the type hierarchy.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::unique_ptr< raw_pwrite_stream > OS, BackendConsumer *BC=nullptr)
static ASTFileSignature createDISentinel()
Extra information about a function prototype.