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/TargetRegistry.h"
37 using namespace clang;
39 #define DEBUG_TYPE "pchcontainer"
44 const std::string MainFileName;
52 std::unique_ptr<llvm::LLVMContext> VMContext;
53 std::unique_ptr<llvm::Module> M;
54 std::unique_ptr<CodeGen::CodeGenModule>
Builder;
55 raw_pwrite_stream *OS;
56 std::shared_ptr<PCHBuffer>
Buffer;
65 : DI(DI), Ctx(Ctx), SkipTagDecls(SkipTagDecls) {}
68 static bool CanRepresent(
const Type *Ty) {
73 auto *Import = cast<ImportDecl>(D);
74 if (!Import->getImportedOwningModule())
83 if (SkipTagDecls && isa<TagDecl>(D))
94 if (!QualTy.isNull() && CanRepresent(QualTy.getTypePtr()))
100 if (isa<CXXMethodDecl>(D))
106 for (
auto i : D->
params())
107 ArgTypes.push_back(i->getType());
120 bool selfIsPseudoStrong, selfIsConsumed;
123 selfIsPseudoStrong, selfIsConsumed));
125 for (
auto i : D->
params())
126 ArgTypes.push_back(i->getType());
137 PCHContainerGenerator(
CompilerInstance &CI,
const std::string &MainFileName,
138 const std::string &OutputFileName,
139 raw_pwrite_stream *OS,
140 std::shared_ptr<PCHBuffer>
Buffer)
149 CodeGenOpts.CodeModel =
"default";
150 CodeGenOpts.ThreadModel =
"single";
151 CodeGenOpts.DebugTypeExtRefs =
true;
155 ~PCHContainerGenerator()
override =
default;
158 assert(!Ctx &&
"initialized multiple times");
161 VMContext.reset(
new llvm::LLVMContext());
162 M.reset(
new llvm::Module(MainFileName, *VMContext));
163 M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
165 *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
166 Builder->getModuleDebugInfo()->setModuleMap(MMap);
170 if (Diags.hasErrorOccurred())
175 if (!
I->isFromASTFile()) {
176 DebugTypeVisitor DTV(*
Builder->getModuleDebugInfo(), *Ctx,
true);
182 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef D)
override {
183 HandleTopLevelDecl(D);
186 void HandleTagDeclDefinition(
TagDecl *D)
override {
187 if (Diags.hasErrorOccurred())
193 DebugTypeVisitor DTV(*
Builder->getModuleDebugInfo(), *Ctx,
false);
195 Builder->UpdateCompletedType(D);
198 void HandleTagDeclRequiredDefinition(
const TagDecl *D)
override {
199 if (Diags.hasErrorOccurred())
202 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
203 Builder->getModuleDebugInfo()->completeRequiredType(RD);
207 void HandleTranslationUnit(
ASTContext &Ctx)
override {
208 assert(M && VMContext &&
Builder);
210 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
211 std::unique_ptr<llvm::Module> M = std::move(this->M);
212 std::unique_ptr<CodeGen::CodeGenModule>
Builder = std::move(this->Builder);
214 if (Diags.hasErrorOccurred())
219 Builder->getModuleDebugInfo()->setDwoId(Buffer->Signature);
228 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(),
Error))
229 llvm::report_fatal_error(Error);
232 assert(Buffer->IsComplete &&
"serialization did not complete");
233 auto &SerializedAST = Buffer->Data;
234 auto Size = SerializedAST.size();
235 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
236 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
237 auto *Data = llvm::ConstantDataArray::getString(
238 *VMContext, StringRef(SerializedAST.data(), Size),
240 auto *ASTSym =
new llvm::GlobalVariable(
244 ASTSym->setAlignment(8);
247 if (Triple.isOSBinFormatMachO())
248 ASTSym->setSection(
"__CLANG,__clangast");
250 else if (Triple.isOSBinFormatCOFF())
251 ASTSym->setSection(
"clangast");
253 ASTSym->setSection(
"__clangast");
258 llvm::raw_svector_ostream OS(Buffer);
275 SerializedAST = std::move(Empty);
281 std::unique_ptr<ASTConsumer>
282 ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
284 const std::string &OutputFileName, llvm::raw_pwrite_stream *OS,
285 std::shared_ptr<PCHBuffer>
Buffer)
const {
286 return llvm::make_unique<PCHContainerGenerator>(CI, MainFileName,
287 OutputFileName, OS,
Buffer);
290 void ObjectFilePCHContainerReader::ExtractPCH(
291 llvm::MemoryBufferRef
Buffer, llvm::BitstreamReader &StreamFile)
const {
292 if (
auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) {
293 auto *Obj = OF.get().get();
294 bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj);
296 for (
auto &Section : OF->get()->sections()) {
299 if ((!IsCOFF && Name ==
"__clangast") ||
300 ( IsCOFF && Name ==
"clangast")) {
302 Section.getContents(Buf);
303 StreamFile.init((
const unsigned char *)Buf.begin(),
304 (
const unsigned char *)Buf.end());
311 StreamFile.init((
const unsigned char *)Buffer.getBufferStart(),
312 (
const unsigned char *)Buffer.getBufferEnd());
Defines the clang::ASTContext interface.
LangOptions & getLangOpts()
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
PreprocessorOptions & getPreprocessorOpts()
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.
const char * getDataLayoutString() const
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.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
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
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.
void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, raw_pwrite_stream *OS)
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.
HeaderSearchOptions & getHeaderSearchOpts()
A class that does preorder depth-first traversal on the entire Clang AST and visits each node...
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...
StringRef getName() const
Return the actual identifier string.
Defines the clang::Preprocessor interface.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Emit native object files.
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.
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.
TagDecl - Represents the declaration of a struct/union/class/enum.
QualType getReturnType() const
Describes a module import declaration, which makes the contents of the named module visible in the cu...
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
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.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Defines the Diagnostic-related interfaces.
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.
Limit generated debug info to reduce size (-fno-standalone-debug).
SourceLocation getLocation() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
TargetOptions & getTargetOpts()