48b4a4e934
the callbacks must be triggered for those, too. As they are not part of a transaction (think "module") they are now sent to the deserialization listener. This can be removed once the modules work. Set the state of the transaction to Committing before the static init - which might trigger more decls even though CodeGen has been run over the decls. Forward DeclCollector::HandleInterestingDecl() to DeclCollector::HandleTopLevelDecl() for decls from the AST reader / from headers describing libraries. Empty transactions must be passed to TCling; they trigger the sending of deserialized decls to ROOT/Meta. Don't start TCling's artificial TU Transaction if the transaction coming in is empty - we need a decl to get the ASTContext. Swap the deserialized decls before handling them in TCling, such that nested calls don't see the same decls again. git-svn-id: http://root.cern.ch/svn/root/trunk@49197 27541ba8-7e3a-0410-8455-c3a389f83636
165 lines
6.0 KiB
C++
165 lines
6.0 KiB
C++
//------------------------------------------------------------------------------
|
|
// CLING - the C++ LLVM-based InterpreterG :)
|
|
// version: $Id$
|
|
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include "DeclCollector.h"
|
|
|
|
#include "cling/Interpreter/Interpreter.h"
|
|
#include "cling/Interpreter/Transaction.h"
|
|
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/AST/DeclCXX.h"
|
|
#include "clang/AST/DeclGroup.h"
|
|
#include "clang/Serialization/ASTDeserializationListener.h"
|
|
|
|
#include "clang/CodeGen/ModuleBuilder.h"
|
|
|
|
using namespace clang;
|
|
|
|
namespace cling {
|
|
bool DeclCollector::comesFromASTReader(DeclGroupRef DGR) const {
|
|
assert(!DGR.isNull() && "DeclGroupRef is Null!");
|
|
if (m_CurTransaction->getCompilationOpts().CodeGenerationForModule)
|
|
return true;
|
|
|
|
// Take the first/only decl in the group.
|
|
Decl* D = *DGR.begin();
|
|
return D->isFromASTFile();
|
|
}
|
|
|
|
bool DeclCollector::shouldIgnoreDeclFromASTReader(const Decl* D) const {
|
|
// Functions that are inlined must be sent to CodeGen - they will not have a
|
|
// symbol in the library.
|
|
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D))
|
|
return !FD->isInlined();
|
|
|
|
// Don't codegen statics coming in from a module; they are already part of
|
|
// the library.
|
|
if (const VarDecl* VD = dyn_cast<VarDecl>(D))
|
|
if (VD->hasGlobalStorage())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// pin the vtable here.
|
|
DeclCollector::~DeclCollector() {
|
|
}
|
|
|
|
bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) {
|
|
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
|
|
// pipe it directly to codegen.
|
|
if (comesFromASTReader(DGR)) {
|
|
if (m_CodeGen) {
|
|
for (DeclGroupRef::iterator I = DGR.begin(), E = DGR.end();
|
|
I != E; ++I)
|
|
if (NamespaceDecl* ND = dyn_cast<NamespaceDecl>(*I)) {
|
|
for (NamespaceDecl::decl_iterator IN = ND->decls_begin(),
|
|
EN = ND->decls_end(); IN != EN; ++IN)
|
|
// Recurse over decls inside the namespace, like
|
|
// CodeGenModule::EmitNamespace() does.
|
|
HandleTopLevelDecl(DeclGroupRef(*IN));
|
|
} else if (!shouldIgnoreDeclFromASTReader(*I)) {
|
|
m_CodeGen->HandleTopLevelDecl(DeclGroupRef(*I));
|
|
// FIXME: once modules are there this is not needed anymore.
|
|
// it is used to simulate modules and the ASTDeserializationListener
|
|
// for sources that are included to describe the library that was
|
|
// built from the sources (ACLiC).
|
|
if (!(*I)->isFromASTFile() && m_Interp->getASTDeserializationListener())
|
|
m_Interp->getASTDeserializationListener()->DeclRead(0, *I);
|
|
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleTopLevelDecl);
|
|
m_CurTransaction->append(DCI);
|
|
return true;
|
|
}
|
|
|
|
void DeclCollector::HandleInterestingDecl(DeclGroupRef DGR) {
|
|
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
|
|
// pipe it directly to codegen.
|
|
if (comesFromASTReader(DGR)) {
|
|
HandleTopLevelDecl(DGR);
|
|
return;
|
|
}
|
|
|
|
Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleInterestingDecl);
|
|
m_CurTransaction->append(DCI);
|
|
}
|
|
|
|
void DeclCollector::HandleTagDeclDefinition(TagDecl* TD) {
|
|
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
|
|
// pipe it directly to codegen.
|
|
if (comesFromASTReader(DeclGroupRef(TD))) {
|
|
if (m_CodeGen)
|
|
m_CodeGen->HandleTagDeclDefinition(TD);
|
|
return;
|
|
}
|
|
|
|
Transaction::DelayCallInfo DCI(DeclGroupRef(TD),
|
|
Transaction::kCCIHandleTagDeclDefinition);
|
|
m_CurTransaction->append(DCI);
|
|
}
|
|
|
|
void DeclCollector::HandleVTable(CXXRecordDecl* RD, bool DefinitionRequired) {
|
|
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
|
|
// pipe it directly to codegen.
|
|
if (comesFromASTReader(DeclGroupRef(RD))) {
|
|
// FIXME: when is the vtable part of the library?
|
|
if (m_CodeGen)
|
|
m_CodeGen->HandleVTable(RD, DefinitionRequired);
|
|
return;
|
|
}
|
|
|
|
Transaction::DelayCallInfo DCI(DeclGroupRef(RD),
|
|
Transaction::kCCIHandleVTable);
|
|
m_CurTransaction->append(DCI);
|
|
|
|
// Intentional no-op. It comes through Sema::DefineUsedVTables, which
|
|
// comes either Sema::ActOnEndOfTranslationUnit or while instantiating a
|
|
// template. In our case we will do it on transaction commit, without
|
|
// keeping track of used vtables, because we have cases where we bypass the
|
|
// clang/AST and directly ask the module so that we have to generate
|
|
// everything without extra smartness.
|
|
}
|
|
|
|
void DeclCollector::CompleteTentativeDefinition(VarDecl* VD) {
|
|
assert(0 && "Not implemented yet!");
|
|
}
|
|
|
|
void DeclCollector::HandleTranslationUnit(ASTContext& Ctx) {
|
|
}
|
|
|
|
void DeclCollector::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {
|
|
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
|
|
// pipe it directly to codegen.
|
|
if (comesFromASTReader(DeclGroupRef(D))) {
|
|
if (m_CodeGen)
|
|
m_CodeGen->HandleCXXImplicitFunctionInstantiation(D);
|
|
return;
|
|
}
|
|
|
|
Transaction::DelayCallInfo DCI(DeclGroupRef(D),
|
|
Transaction::kCCIHandleCXXImplicitFunctionInstantiation);
|
|
m_CurTransaction->append(DCI);
|
|
}
|
|
void DeclCollector::HandleCXXStaticMemberVarInstantiation(VarDecl *D) {
|
|
// if that decl comes from an AST File, i.e. PCH/PCM, no transaction needed
|
|
// pipe it directly to codegen.
|
|
if (comesFromASTReader(DeclGroupRef(D))) {
|
|
if (m_CodeGen && !shouldIgnoreDeclFromASTReader(D))
|
|
m_CodeGen->HandleCXXStaticMemberVarInstantiation(D);
|
|
return;
|
|
}
|
|
|
|
Transaction::DelayCallInfo DCI(DeclGroupRef(D),
|
|
Transaction::kCCIHandleCXXStaticMemberVarInstantiation);
|
|
m_CurTransaction->append(DCI);
|
|
}
|
|
|
|
} // namespace cling
|