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.setDebuggerTuning(CI.
getCodeGenOpts().getDebuggerTuning());
159 ~PCHContainerGenerator()
override =
default;
162 assert(!Ctx &&
"initialized multiple times");
165 VMContext.reset(
new llvm::LLVMContext());
166 M.reset(
new llvm::Module(MainFileName, *VMContext));
167 M->setDataLayout(Ctx->getTargetInfo().getDataLayout());
169 *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
172 auto *DI =
Builder->getModuleDebugInfo();
173 StringRef ModuleName = llvm::sys::path::filename(MainFileName);
174 DI->setPCHDescriptor({ModuleName,
"", OutputFileName, ~1ULL});
175 DI->setModuleMap(MMap);
179 if (Diags.hasErrorOccurred())
184 if (!
I->isFromASTFile()) {
185 DebugTypeVisitor DTV(*
Builder->getModuleDebugInfo(), *Ctx);
191 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef D)
override {
192 HandleTopLevelDecl(D);
195 void HandleTagDeclDefinition(
TagDecl *D)
override {
196 if (Diags.hasErrorOccurred())
199 if (D->isFromASTFile())
207 auto *DeclCtx = D->getDeclContext();
209 if (
auto *D = dyn_cast<TagDecl>(DeclCtx))
215 DebugTypeVisitor DTV(*
Builder->getModuleDebugInfo(), *Ctx);
217 Builder->UpdateCompletedType(D);
220 void HandleTagDeclRequiredDefinition(
const TagDecl *D)
override {
221 if (Diags.hasErrorOccurred())
224 if (
const RecordDecl *RD = dyn_cast<RecordDecl>(D))
225 Builder->getModuleDebugInfo()->completeRequiredType(RD);
229 void HandleTranslationUnit(
ASTContext &Ctx)
override {
230 assert(M && VMContext &&
Builder);
232 std::unique_ptr<llvm::LLVMContext> VMContext = std::move(this->VMContext);
233 std::unique_ptr<llvm::Module> M = std::move(this->M);
234 std::unique_ptr<CodeGen::CodeGenModule>
Builder = std::move(this->Builder);
236 if (Diags.hasErrorOccurred())
244 uint64_t Signature = Buffer->Signature ? Buffer->Signature : ~1ULL;
245 Builder->getModuleDebugInfo()->setDwoId(Signature);
254 if (!llvm::TargetRegistry::lookupTarget(Triple.getTriple(),
Error))
255 llvm::report_fatal_error(Error);
258 assert(Buffer->IsComplete &&
"serialization did not complete");
259 auto &SerializedAST = Buffer->Data;
260 auto Size = SerializedAST.size();
261 auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
262 auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
263 auto *Data = llvm::ConstantDataArray::getString(
264 *VMContext, StringRef(SerializedAST.data(), Size),
266 auto *ASTSym =
new llvm::GlobalVariable(
270 ASTSym->setAlignment(8);
273 if (Triple.isOSBinFormatMachO())
274 ASTSym->setSection(
"__CLANG,__clangast");
276 else if (Triple.isOSBinFormatCOFF())
277 ASTSym->setSection(
"clangast");
279 ASTSym->setSection(
"__clangast");
285 Diags, CodeGenOpts, TargetOpts, LangOpts,
288 llvm::make_unique<llvm::raw_svector_ostream>(
Buffer));
299 SerializedAST = std::move(Empty);
305 std::unique_ptr<ASTConsumer>
306 ObjectFilePCHContainerWriter::CreatePCHContainerGenerator(
308 const std::string &OutputFileName,
309 std::unique_ptr<llvm::raw_pwrite_stream> OS,
310 std::shared_ptr<PCHBuffer>
Buffer)
const {
311 return llvm::make_unique<PCHContainerGenerator>(
312 CI, MainFileName, OutputFileName, std::move(OS),
Buffer);
315 void ObjectFilePCHContainerReader::ExtractPCH(
316 llvm::MemoryBufferRef
Buffer, llvm::BitstreamReader &StreamFile)
const {
317 if (
auto OF = llvm::object::ObjectFile::createObjectFile(Buffer)) {
318 auto *Obj = OF.get().get();
319 bool IsCOFF = isa<llvm::object::COFFObjectFile>(Obj);
321 for (
auto &Section : OF->get()->sections()) {
324 if ((!IsCOFF && Name ==
"__clangast") ||
325 ( IsCOFF && Name ==
"clangast")) {
327 Section.getContents(Buf);
328 StreamFile.init((
const unsigned char *)Buf.begin(),
329 (
const unsigned char *)Buf.end());
336 StreamFile.init((
const unsigned char *)Buffer.getBufferStart(),
337 (
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()
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.
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
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
CodeGenOptions & getCodeGenOpts()
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.
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...
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.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
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 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
void EmitBackendOutput(DiagnosticsEngine &Diags, 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)
Defines the clang::TargetInfo interface.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const llvm::DataLayout & getDataLayout() const
TargetOptions & getTargetOpts()