23#include "llvm/ADT/StringRef.h"
24#include "llvm/Bitstream/BitstreamReader.h"
25#include "llvm/DebugInfo/DWARF/DWARFContext.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/DataLayout.h"
28#include "llvm/IR/LLVMContext.h"
29#include "llvm/IR/Module.h"
30#include "llvm/MC/TargetRegistry.h"
31#include "llvm/Object/COFF.h"
32#include "llvm/Object/ObjectFile.h"
33#include "llvm/Support/Path.h"
39#define DEBUG_TYPE "pchcontainer"
44 const std::string MainFileName;
45 const std::string OutputFileName;
54 std::unique_ptr<llvm::LLVMContext> VMContext;
55 std::unique_ptr<llvm::Module> M;
56 std::unique_ptr<CodeGen::CodeGenModule> Builder;
57 std::unique_ptr<raw_pwrite_stream> OS;
58 std::shared_ptr<PCHBuffer> Buffer;
68 static bool CanRepresent(
const Type *Ty) {
82 if (
auto *TD = dyn_cast<TagDecl>(
D))
83 if (!TD->isCompleteDefinition())
101 if (isa<CXXDeductionGuideDecl>(
D))
104 if (isa<CXXMethodDecl>(
D))
110 for (
auto *i :
D->parameters())
111 ArgTypes.push_back(i->getType());
121 if (!
D->getClassInterface())
124 bool selfIsPseudoStrong, selfIsConsumed;
126 ArgTypes.push_back(
D->getSelfType(Ctx,
D->getClassInterface(),
127 selfIsPseudoStrong, selfIsConsumed));
129 for (
auto *i :
D->parameters())
130 ArgTypes.push_back(i->getType());
141 PCHContainerGenerator(
CompilerInstance &CI,
const std::string &MainFileName,
142 const std::string &OutputFileName,
143 std::unique_ptr<raw_pwrite_stream> OS,
144 std::shared_ptr<PCHBuffer> Buffer)
146 OutputFileName(OutputFileName), Ctx(
nullptr),
152 OS(std::move(OS)), Buffer(std::move(Buffer)) {
156 LangOpts.setThreadModel(LangOptions::ThreadModelKind::Single);
157 CodeGenOpts.DebugTypeExtRefs =
true;
161 CodeGenOpts.setDebugInfo(llvm::codegenoptions::FullDebugInfo);
162 CodeGenOpts.setDebuggerTuning(CI.
getCodeGenOpts().getDebuggerTuning());
168 CodeGenOpts.DebugStrictDwarf = CI.
getCodeGenOpts().DebugStrictDwarf;
171 ~PCHContainerGenerator()
override =
default;
174 assert(!Ctx &&
"initialized multiple times");
177 VMContext.reset(
new llvm::LLVMContext());
178 M.reset(
new llvm::Module(MainFileName, *VMContext));
181 *Ctx, FS, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
184 auto *DI = Builder->getModuleDebugInfo();
185 StringRef ModuleName = llvm::sys::path::filename(MainFileName);
186 DI->setPCHDescriptor(
188 DI->setModuleMap(MMap);
197 if (!
I->isFromASTFile()) {
198 DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
216 if (
D->getName().empty())
222 if (
auto *
D = dyn_cast<TagDecl>(DeclCtx))
223 if (!
D->isCompleteDefinition())
228 DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
230 Builder->UpdateCompletedType(
D);
237 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(
D))
238 Builder->getModuleDebugInfo()->completeRequiredType(RD);
243 Builder->getModuleDebugInfo()->EmitImportDecl(*
D);
248 assert(M && VMContext && Builder);
250 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
251 std::unique_ptr<llvm::Module> M = std::move(this->M);
252 std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
265 Buffer->Signature ? Buffer->Signature.truncatedValue() : ~1ULL;
267 Builder->getModuleDebugInfo()->setDwoId(Signature);
276 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(), Error))
277 llvm::report_fatal_error(llvm::Twine(Error));
280 assert(Buffer->IsComplete &&
"serialization did not complete");
281 auto &SerializedAST = Buffer->Data;
282 auto Size = SerializedAST.size();
284 if (Triple.isOSBinFormatWasm()) {
290 llvm::NamedMDNode *MD =
291 M->getOrInsertNamedMetadata(
"wasm.custom_sections");
292 llvm::Metadata *Ops[2] = {
293 llvm::MDString::get(*VMContext,
"__clangast"),
294 llvm::MDString::get(*VMContext,
295 StringRef(SerializedAST.data(), Size))};
296 auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops);
297 MD->addOperand(NameAndContent);
299 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
300 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
301 auto *
Data = llvm::ConstantDataArray::getString(
302 *VMContext, StringRef(SerializedAST.data(), Size),
304 auto *ASTSym =
new llvm::GlobalVariable(
305 *M, Ty,
true, llvm::GlobalVariable::InternalLinkage,
306 Data,
"__clang_ast");
308 ASTSym->setAlignment(llvm::Align(8));
311 if (Triple.isOSBinFormatMachO())
312 ASTSym->setSection(
"__CLANG,__clangast");
314 else if (Triple.isOSBinFormatCOFF())
315 ASTSym->setSection(
"clangast");
317 ASTSym->setSection(
"__clangast");
324 Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
326 BackendAction::Backend_EmitLL, FS,
327 std::make_unique<llvm::raw_svector_ostream>(Buffer));
328 llvm::dbgs() << Buffer;
335 BackendAction::Backend_EmitObj, FS, std::move(OS));
339 SerializedAST = std::move(
Empty);
345std::unique_ptr<ASTConsumer>
346ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
348 const std::string &OutputFileName,
349 std::unique_ptr<llvm::raw_pwrite_stream> OS,
350 std::shared_ptr<PCHBuffer> Buffer)
const {
351 return std::make_unique<PCHContainerGenerator>(
352 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.