Provide a hook for the benefit of clients using clang IR gen as a subroutine:

emit metadata associating allocas and global values with a Decl*.  This feature
is controlled by an option that (intentionally) cannot be enabled on the command
line.

To use this feature, simply set
  CodeGenOptions.EmitDeclMetadata = true;
and then interpret the completely underspecified metadata. :)

llvm-svn: 107739
This commit is contained in:
John McCall 2010-07-06 23:57:41 +00:00
parent da534381f8
commit 09ae03299a
5 changed files with 84 additions and 0 deletions

View File

@ -67,6 +67,9 @@ public:
unsigned UnwindTables : 1; /// Emit unwind tables.
unsigned VerifyModule : 1; /// Control whether the module should be run
/// through the LLVM Verifier.
unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl*
/// various IR entities came from. Only useful
/// when running CodeGen as a subroutine.
/// The code model to use (-mcmodel).
std::string CodeModel;
@ -122,6 +125,7 @@ public:
UnrollLoops = 0;
UnwindTables = 0;
VerifyModule = 1;
EmitDeclMetadata = 0;
Inlining = NoInlining;
RelocationModel = "pic";

View File

@ -173,6 +173,9 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EmitIfUsed(*this, TerminateLandingPad);
EmitIfUsed(*this, TerminateHandler);
EmitIfUsed(*this, UnreachableBlock);
if (CGM.getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
}
/// ShouldInstrumentFunction - Return true if the current function should be

View File

@ -1548,6 +1548,8 @@ private:
const TargetCodeGenInfo &getTargetHooks() const {
return CGM.getTargetCodeGenInfo();
}
void EmitDeclMetadata();
};

View File

@ -104,6 +104,9 @@ void CodeGenModule::Release() {
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitAnnotations();
EmitLLVMUsed();
if (getCodeGenOpts().EmitDeclMetadata)
EmitDeclMetadata();
}
bool CodeGenModule::isTargetDarwin() const {
@ -2036,3 +2039,73 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
assert(isa<TypeDecl>(D) && "Unsupported decl kind");
}
}
/// Turns the given pointer into a constant.
static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
const void *Ptr) {
uintptr_t PtrInt = reinterpret_cast<uintptr_t>(Ptr);
const llvm::Type *i64 = llvm::Type::getInt64Ty(Context);
return llvm::ConstantInt::get(i64, PtrInt);
}
static void EmitGlobalDeclMetadata(CodeGenModule &CGM,
llvm::NamedMDNode *&GlobalMetadata,
GlobalDecl D,
llvm::GlobalValue *Addr) {
if (!GlobalMetadata)
GlobalMetadata =
CGM.getModule().getOrInsertNamedMetadata("clang.global.decl.ptrs");
// TODO: should we report variant information for ctors/dtors?
llvm::Value *Ops[] = {
Addr,
GetPointerConstant(CGM.getLLVMContext(), D.getDecl())
};
GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops, 2));
}
/// Emits metadata nodes associating all the global values in the
/// current module with the Decls they came from. This is useful for
/// projects using IR gen as a subroutine.
///
/// Since there's currently no way to associate an MDNode directly
/// with an llvm::GlobalValue, we create a global named metadata
/// with the name 'clang.global.decl.ptrs'.
void CodeGenModule::EmitDeclMetadata() {
llvm::NamedMDNode *GlobalMetadata = 0;
// StaticLocalDeclMap
for (llvm::DenseMap<GlobalDecl,llvm::StringRef>::iterator
I = MangledDeclNames.begin(), E = MangledDeclNames.end();
I != E; ++I) {
llvm::GlobalValue *Addr = getModule().getNamedValue(I->second);
EmitGlobalDeclMetadata(*this, GlobalMetadata, I->first, Addr);
}
}
/// Emits metadata nodes for all the local variables in the current
/// function.
void CodeGenFunction::EmitDeclMetadata() {
if (LocalDeclMap.empty()) return;
llvm::LLVMContext &Context = getLLVMContext();
// Find the unique metadata ID for this name.
unsigned DeclPtrKind = Context.getMDKindID("clang.decl.ptr");
llvm::NamedMDNode *GlobalMetadata = 0;
for (llvm::DenseMap<const Decl*, llvm::Value*>::iterator
I = LocalDeclMap.begin(), E = LocalDeclMap.end(); I != E; ++I) {
const Decl *D = I->first;
llvm::Value *Addr = I->second;
if (llvm::AllocaInst *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) {
llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D);
Alloca->setMetadata(DeclPtrKind, llvm::MDNode::get(Context, &DAddr, 1));
} else if (llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(Addr)) {
GlobalDecl GD = GlobalDecl(cast<VarDecl>(D));
EmitGlobalDeclMetadata(CGM, GlobalMetadata, GD, GV);
}
}
}

View File

@ -594,6 +594,8 @@ private:
/// references to global which may otherwise be optimized out.
void EmitLLVMUsed(void);
void EmitDeclMetadata();
/// MayDeferGeneration - Determine if the given decl can be emitted
/// lazily; this is only relevant for definitions. The given decl
/// must be either a function or var decl.