forked from OSchip/llvm-project
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:
parent
da534381f8
commit
09ae03299a
|
@ -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";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1548,6 +1548,8 @@ private:
|
|||
const TargetCodeGenInfo &getTargetHooks() const {
|
||||
return CGM.getTargetCodeGenInfo();
|
||||
}
|
||||
|
||||
void EmitDeclMetadata();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue