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/Object/COFF.h" 31 #include "llvm/Object/ObjectFile.h" 32 #include "llvm/Support/Path.h" 33 #include "llvm/Support/TargetRegistry.h" 37 using namespace clang;
39 #define DEBUG_TYPE "pchcontainer" 44 const std::string MainFileName;
45 const std::string OutputFileName;
53 std::unique_ptr<llvm::LLVMContext> VMContext;
54 std::unique_ptr<llvm::Module> M;
55 std::unique_ptr<CodeGen::CodeGenModule> Builder;
56 std::unique_ptr<raw_pwrite_stream> OS;
57 std::shared_ptr<PCHBuffer> Buffer;
67 static bool CanRepresent(
const Type *Ty) {
81 if (
auto *TD = dyn_cast<TagDecl>(D))
82 if (!TD->isCompleteDefinition())
93 if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
99 if (isa<CXXMethodDecl>(D))
106 ArgTypes.push_back(i->getType());
119 bool selfIsPseudoStrong, selfIsConsumed;
122 selfIsPseudoStrong, selfIsConsumed));
125 ArgTypes.push_back(i->getType());
136 PCHContainerGenerator(
CompilerInstance &CI,
const std::string &MainFileName,
137 const std::string &OutputFileName,
138 std::unique_ptr<raw_pwrite_stream> OS,
139 std::shared_ptr<PCHBuffer> Buffer)
141 OutputFileName(OutputFileName), Ctx(
nullptr),
146 OS(std::move(OS)), Buffer(std::move(Buffer)) {
151 CodeGenOpts.DebugTypeExtRefs =
true;
156 CodeGenOpts.setDebuggerTuning(CI.
getCodeGenOpts().getDebuggerTuning());
161 ~PCHContainerGenerator()
override =
default;
163 void Initialize(
ASTContext &Context)
override {
164 assert(!Ctx &&
"initialized multiple times");
167 VMContext.reset(
new llvm::LLVMContext());
168 M.reset(
new llvm::Module(MainFileName, *VMContext));
171 *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
174 auto *DI = Builder->getModuleDebugInfo();
175 StringRef ModuleName = llvm::sys::path::filename(MainFileName);
176 DI->setPCHDescriptor({ModuleName,
"", OutputFileName,
178 DI->setModuleMap(MMap);
187 if (!I->isFromASTFile()) {
188 DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
194 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef D)
override {
195 HandleTopLevelDecl(D);
198 void HandleTagDeclDefinition(
TagDecl *D)
override {
212 if (
auto *D = dyn_cast<TagDecl>(DeclCtx))
218 DebugTypeVisitor DTV(*Builder->getModuleDebugInfo(), *Ctx);
220 Builder->UpdateCompletedType(D);
223 void HandleTagDeclRequiredDefinition(
const TagDecl *D)
override {
227 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
228 Builder->getModuleDebugInfo()->completeRequiredType(RD);
231 void HandleImplicitImportDecl(
ImportDecl *D)
override {
233 Builder->getModuleDebugInfo()->EmitImportDecl(*D);
237 void HandleTranslationUnit(
ASTContext &Ctx)
override {
238 assert(M && VMContext && Builder);
240 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
241 std::unique_ptr<llvm::Module> M = std::move(this->M);
242 std::unique_ptr<CodeGen::CodeGenModule> Builder = std::move(this->Builder);
255 ? (uint64_t)Buffer->Signature[1] << 32 | Buffer->Signature[0]
257 Builder->getModuleDebugInfo()->setDwoId(Signature);
266 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(),
Error))
267 llvm::report_fatal_error(Error);
270 assert(Buffer->IsComplete &&
"serialization did not complete");
271 auto &SerializedAST = Buffer->Data;
272 auto Size = SerializedAST.size();
273 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
274 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
275 auto *Data = llvm::ConstantDataArray::getString(
276 *VMContext, StringRef(SerializedAST.data(), Size),
278 auto *ASTSym =
new llvm::GlobalVariable(
282 ASTSym->setAlignment(llvm::Align(8));
285 if (Triple.isOSBinFormatMachO())
286 ASTSym->setSection(
"__CLANG,__clangast");
288 else if (Triple.isOSBinFormatCOFF())
289 ASTSym->setSection(
"clangast");
291 ASTSym->setSection(
"__clangast");
297 Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts,
300 std::make_unique<llvm::raw_svector_ostream>(Buffer));
301 llvm::dbgs() << Buffer;
312 SerializedAST = std::move(Empty);
318 std::unique_ptr<ASTConsumer>
319 ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
321 const std::string &OutputFileName,
322 std::unique_ptr<llvm::raw_pwrite_stream> OS,
323 std::shared_ptr<PCHBuffer> Buffer)
const {
324 return std::make_unique<PCHContainerGenerator>(
325 CI, MainFileName, OutputFileName, std::move(OS), Buffer);
329 ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer)
const {
331 auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
333 auto &OF = OFOrErr.get();
334 bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF);
336 for (
auto &Section : OF->sections()) {
341 consumeError(NameOrErr.takeError());
343 if ((!IsCOFF && Name ==
"__clangast") || (IsCOFF && Name ==
"clangast")) {
347 handleAllErrors(E.takeError(), [&](
const llvm::ErrorInfoBase &EIB) {
348 EIB.log(llvm::errs());
355 handleAllErrors(OFOrErr.takeError(), [&](
const llvm::ErrorInfoBase &EIB) {
356 if (EIB.convertToErrorCode() ==
357 llvm::object::object_error::invalid_file_type)
359 PCH = Buffer.getBuffer();
361 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.
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.
void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType, llvm::Function *Fn=nullptr)
Emit debug info for a function declaration.
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