25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/Bitcode/BitstreamReader.h"
27 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
28 #include "llvm/IR/Constants.h"
29 #include "llvm/IR/DataLayout.h"
30 #include "llvm/IR/LLVMContext.h"
31 #include "llvm/IR/Module.h"
32 #include "llvm/Object/COFF.h"
33 #include "llvm/Object/ObjectFile.h"
34 #include "llvm/Support/Path.h"
35 #include "llvm/Support/TargetRegistry.h"
39 using namespace clang;
41 #define DEBUG_TYPE "pchcontainer"
46 const std::string MainFileName;
47 const std::string OutputFileName;
55 std::unique_ptr<llvm::LLVMContext> VMContext;
56 std::unique_ptr<llvm::Module> M;
57 std::unique_ptr<CodeGen::CodeGenModule>
Builder;
58 std::unique_ptr<raw_pwrite_stream> OS;
59 std::shared_ptr<PCHBuffer>
Buffer;
69 static bool CanRepresent(
const Type *Ty) {
74 auto *Import = cast<ImportDecl>(D);
75 if (!Import->getImportedOwningModule())
84 if (
auto *TD = dyn_cast<TagDecl>(D))
85 if (!TD->isCompleteDefinition())
96 if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
102 if (isa<CXXMethodDecl>(D))
109 ArgTypes.push_back(i->getType());
122 bool selfIsPseudoStrong, selfIsConsumed;
125 selfIsPseudoStrong, selfIsConsumed));
128 ArgTypes.push_back(i->getType());
139 PCHContainerGenerator(
CompilerInstance &CI,
const std::string &MainFileName,
140 const std::string &OutputFileName,
141 std::unique_ptr<raw_pwrite_stream> OS,
142 std::shared_ptr<PCHBuffer>
Buffer)
144 OutputFileName(OutputFileName), Ctx(
nullptr),
149 OS(std::move(OS)),
Buffer(std::move(Buffer)) {
152 CodeGenOpts.CodeModel =
"default";
153 CodeGenOpts.ThreadModel =
"single";
154 CodeGenOpts.DebugTypeExtRefs =
true;
156 CodeGenOpts.MainFileName =
157 LangOpts.CurrentModule.empty() ? MainFileName : LangOpts.CurrentModule;
159 CodeGenOpts.setDebuggerTuning(CI.
getCodeGenOpts().getDebuggerTuning());
162 ~PCHContainerGenerator()
override =
default;
165 assert(!Ctx &&
"initialized multiple times");
168 VMContext.reset(
new llvm::LLVMContext());
169 M.reset(
new llvm::Module(MainFileName, *VMContext));
170 M->setDataLayout(Ctx->getTargetInfo().getDataLayout());
172 *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
175 auto *DI =
Builder->getModuleDebugInfo();
176 StringRef ModuleName = llvm::sys::path::filename(MainFileName);
177 DI->setPCHDescriptor({ModuleName,
"", OutputFileName,
179 DI->setModuleMap(MMap);
183 if (Diags.hasErrorOccurred())
188 if (!
I->isFromASTFile()) {
189 DebugTypeVisitor DTV(*
Builder->getModuleDebugInfo(), *Ctx);
195 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef D)
override {
196 HandleTopLevelDecl(D);
199 void HandleTagDeclDefinition(
TagDecl *D)
override {
200 if (Diags.hasErrorOccurred())
213 if (
auto *D = dyn_cast<TagDecl>(DeclCtx))
219 DebugTypeVisitor DTV(*
Builder->getModuleDebugInfo(), *Ctx);
221 Builder->UpdateCompletedType(D);
224 void HandleTagDeclRequiredDefinition(
const TagDecl *D)
override {
225 if (Diags.hasErrorOccurred())
228 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
229 Builder->getModuleDebugInfo()->completeRequiredType(RD);
233 void HandleTranslationUnit(
ASTContext &Ctx)
override {
234 assert(M && VMContext &&
Builder);
236 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
237 std::unique_ptr<llvm::Module> M = std::move(this->M);
238 std::unique_ptr<CodeGen::CodeGenModule>
Builder = std::move(this->Builder);
240 if (Diags.hasErrorOccurred())
251 ? (uint64_t)Buffer->Signature[1] << 32 | Buffer->Signature[0]
253 Builder->getModuleDebugInfo()->setDwoId(Signature);
262 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(),
Error))
263 llvm::report_fatal_error(Error);
266 assert(Buffer->IsComplete &&
"serialization did not complete");
267 auto &SerializedAST = Buffer->Data;
268 auto Size = SerializedAST.size();
269 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
270 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
271 auto *Data = llvm::ConstantDataArray::getString(
272 *VMContext, StringRef(SerializedAST.data(), Size),
274 auto *ASTSym =
new llvm::GlobalVariable(
278 ASTSym->setAlignment(8);
281 if (Triple.isOSBinFormatMachO())
282 ASTSym->setSection(
"__CLANG,__clangast");
284 else if (Triple.isOSBinFormatCOFF())
285 ASTSym->setSection(
"clangast");
287 ASTSym->setSection(
"__clangast");
293 Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
296 llvm::make_unique<llvm::raw_svector_ostream>(
Buffer));
308 SerializedAST = std::move(Empty);
314 std::unique_ptr<ASTConsumer>
315 ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
317 const std::string &OutputFileName,
318 std::unique_ptr<llvm::raw_pwrite_stream> OS,
319 std::shared_ptr<PCHBuffer>
Buffer)
const {
320 return llvm::make_unique<PCHContainerGenerator>(
321 CI, MainFileName, OutputFileName, std::move(OS),
Buffer);
325 ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef
Buffer)
const {
327 auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
329 auto &OF = OFOrErr.get();
330 bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF);
332 for (
auto &Section : OF->sections()) {
334 Section.getName(Name);
335 if ((!IsCOFF && Name ==
"__clangast") || (IsCOFF && Name ==
"clangast")) {
336 Section.getContents(PCH);
341 handleAllErrors(OFOrErr.takeError(), [&](
const llvm::ErrorInfoBase &EIB) {
342 if (EIB.convertToErrorCode() ==
343 llvm::object::object_error::invalid_file_type)
345 PCH = Buffer.getBuffer();
347 EIB.log(llvm::errs());
Defines the clang::ASTContext interface.
LangOptions & getLangOpts()
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
PreprocessorOptions & getPreprocessorOpts()
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
A (possibly-)qualified type.
ObjCInterfaceDecl * getClassInterface()
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Emit human-readable LLVM assembly.
The base class of the type hierarchy.
std::unique_ptr< llvm::MemoryBuffer > Buffer
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
const Type * getTypeForDecl() const
Options for controlling the target.
Extra information about a function prototype.
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
ObjCMethodDecl - Represents an instance or class method declaration.
RecordDecl - Represents a struct/union/class.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
void EmitImportDecl(const ImportDecl &ID)
Emit an declaration.
QualType getReturnType() const
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
CodeGenOptions & getCodeGenOpts()
The signature of a module, which is a hash of the AST content.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
const TargetInfo & getTargetInfo() const
Concrete class used by the front-end to report problems and issues.
HeaderSearch & getHeaderSearchInfo() const
TypeDecl - Represents a declaration of a type.
Defines the Diagnostic-related interfaces.
HeaderSearchOptions & getHeaderSearchOpts()
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
detail::InMemoryDirectory::const_iterator I
Preprocessor & getPreprocessor() const
Return the current preprocessor.
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
Defines the clang::Preprocessor interface.
DeclContext * getDeclContext()
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Emit native object files.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isFromASTFile() const
Determine whether this declaration came from an AST file (such as a precompiled header or module) rat...
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
ArrayRef< ParmVarDecl * > parameters() const
void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType)
Emit debug info for a function declaration.
QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID, bool &selfIsPseudoStrong, bool &selfIsConsumed)
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Limit generated debug info to reduce size (-fno-standalone-debug).
TagDecl - Represents the declaration of a struct/union/class/enum.
ArrayRef< ParmVarDecl * > parameters() const
QualType getReturnType() const
Describes a module import declaration, which makes the contents of the named module visible in the cu...
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
This class organizes the cross-function state that is used while generating LLVM code.
void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, const llvm::DataLayout &TDesc, llvm::Module *M, BackendAction Action, std::unique_ptr< raw_pwrite_stream > OS)
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
llvm::DIType * getOrCreateStandaloneType(QualType Ty, SourceLocation Loc)
Emit standalone debug info for a type.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
BoundNodesTreeBuilder *const Builder
Defines the clang::TargetInfo interface.
SourceLocation getLocation() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const llvm::DataLayout & getDataLayout() const
TargetOptions & getTargetOpts()