24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/Bitcode/BitstreamReader.h" 26 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 27 #include "llvm/IR/Constants.h" 28 #include "llvm/IR/DataLayout.h" 29 #include "llvm/IR/LLVMContext.h" 30 #include "llvm/IR/Module.h" 31 #include "llvm/Object/COFF.h" 32 #include "llvm/Object/ObjectFile.h" 33 #include "llvm/Support/Path.h" 34 #include "llvm/Support/TargetRegistry.h" 38 using namespace clang;
40 #define DEBUG_TYPE "pchcontainer" 45 const std::string MainFileName;
46 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())
94 if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
100 if (isa<CXXMethodDecl>(D))
107 ArgTypes.push_back(i->getType());
120 bool selfIsPseudoStrong, selfIsConsumed;
123 selfIsPseudoStrong, selfIsConsumed));
126 ArgTypes.push_back(i->getType());
137 PCHContainerGenerator(
CompilerInstance &CI,
const std::string &MainFileName,
138 const std::string &OutputFileName,
139 std::unique_ptr<raw_pwrite_stream> OS,
140 std::shared_ptr<PCHBuffer> Buffer)
142 OutputFileName(OutputFileName), Ctx(
nullptr),
147 OS(std::move(OS)), Buffer(std::move(Buffer)) {
152 CodeGenOpts.DebugTypeExtRefs =
true;
157 CodeGenOpts.setDebuggerTuning(CI.
getCodeGenOpts().getDebuggerTuning());
162 ~PCHContainerGenerator()
override =
default;
164 void Initialize(
ASTContext &Context)
override {
165 assert(!Ctx &&
"initialized multiple times");
168 VMContext.reset(
new llvm::LLVMContext());
169 M.reset(
new llvm::Module(MainFileName, *VMContext));
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);
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 {
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 {
228 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
229 Builder->getModuleDebugInfo()->completeRequiredType(RD);
232 void HandleImplicitImportDecl(
ImportDecl *D)
override {
234 Builder->getModuleDebugInfo()->EmitImportDecl(*D);
238 void HandleTranslationUnit(
ASTContext &Ctx)
override {
239 assert(M && VMContext && Builder);
241 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
242 std::unique_ptr<llvm::Module> M = std::move(this->M);
243 std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
256 ? (uint64_t)Buffer->Signature[1] << 32 | Buffer->Signature[0]
258 Builder->getModuleDebugInfo()->setDwoId(Signature);
267 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(),
Error))
268 llvm::report_fatal_error(Error);
271 assert(Buffer->IsComplete &&
"serialization did not complete");
272 auto &SerializedAST = Buffer->Data;
273 auto Size = SerializedAST.size();
274 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
275 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
276 auto *Data = llvm::ConstantDataArray::getString(
277 *VMContext, StringRef(SerializedAST.data(), Size),
279 auto *ASTSym =
new llvm::GlobalVariable(
283 ASTSym->setAlignment(8);
286 if (Triple.isOSBinFormatMachO())
287 ASTSym->setSection(
"__CLANG,__clangast");
289 else if (Triple.isOSBinFormatCOFF())
290 ASTSym->setSection(
"clangast");
292 ASTSym->setSection(
"__clangast");
298 Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
301 llvm::make_unique<llvm::raw_svector_ostream>(Buffer));
302 llvm::dbgs() << Buffer;
313 SerializedAST = std::move(Empty);
319 std::unique_ptr<ASTConsumer>
320 ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
322 const std::string &OutputFileName,
323 std::unique_ptr<llvm::raw_pwrite_stream> OS,
324 std::shared_ptr<PCHBuffer> Buffer)
const {
325 return llvm::make_unique<PCHContainerGenerator>(
326 CI, MainFileName, OutputFileName, std::move(OS), Buffer);
330 ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer)
const {
332 auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
334 auto &OF = OFOrErr.get();
335 bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF);
337 for (
auto &Section : OF->sections()) {
339 Section.getName(Name);
340 if ((!IsCOFF && Name ==
"__clangast") || (IsCOFF && Name ==
"clangast")) {
341 Section.getContents(PCH);
346 handleAllErrors(OFOrErr.takeError(), [&](
const llvm::ErrorInfoBase &EIB) {
347 if (EIB.convertToErrorCode() ==
348 llvm::object::object_error::invalid_file_type)
350 PCH = Buffer.getBuffer();
352 EIB.log(llvm::errs());
Defines the clang::ASTContext interface.
LangOptions & getLangOpts()
const Type * getTypeForDecl() const
Represents a function declaration or definition.
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
bool hasErrorOccurred() const
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.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
The base class of the type hierarchy.
const TargetInfo & getTargetInfo() const
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
QualType getReturnType() 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.
Represents a struct/union/class.
std::map< std::string, std::string > DebugPrefixMap
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.
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...
std::string CodeModel
The code model to use (-mcmodel).
ArrayRef< ParmVarDecl * > parameters() const
CodeGenOptions & getCodeGenOpts()
HeaderSearch & getHeaderSearchInfo() const
Concrete class used by the front-end to report problems and issues.
Represents a declaration of a type.
Defines the Diagnostic-related interfaces.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
HeaderSearchOptions & getHeaderSearchOpts()
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
QualType getReturnType() const
std::string ThreadModel
The thread model to use.
std::string CurrentModule
The name of the current module, of which the main source file is a part.
Module * getImportedOwningModule() const
Get the imported owning module, if this decl is from an imported (non-local) module.
Defines the clang::Preprocessor interface.
DeclContext * getDeclContext()
Emit native object files.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
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.
Limit generated debug info to reduce size (-fno-standalone-debug).
Represents the declaration of a struct/union/class/enum.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
const llvm::DataLayout & getDataLayout() const
bool isFromASTFile() const
Determine whether this declaration came from an AST file (such as a precompiled header or module) rat...
Describes a module import declaration, which makes the contents of the named module visible in the cu...
This class organizes the cross-function state that is used while generating LLVM code.
Dataflow Directional Tag Classes.
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)
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
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...
Preprocessor & getPreprocessor() const
Return the current preprocessor.
std::string MainFileName
The user provided name for the "main file", if non-empty.
Defines the clang::TargetInfo interface.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
TargetOptions & getTargetOpts()
SourceLocation getLocation() const
ArrayRef< ParmVarDecl * > parameters() const