//===--- DIBuilder.cpp - Debug Information Builder ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the DIBuilder.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/DIBuilder.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Constants.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Dwarf.h"
using namespace llvm;
using namespace llvm::dwarf;
static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) {
assert((Tag & LLVMDebugVersionMask) == 0 &&
"Tag too large for debug encoding!");
return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion);
}
DIBuilder::DIBuilder(Module &m)
: M(m), VMContext(M.getContext()), TheCU(0), TempEnumTypes(0),
TempRetainTypes(0), TempSubprograms(0), TempGVs(0), DeclareFn(0),
ValueFn(0)
{}
/// finalize - Construct any deferred debug info descriptors.
void DIBuilder::finalize() {
DIArray Enums = getOrCreateArray(AllEnumTypes);
DIType(TempEnumTypes).replaceAllUsesWith(Enums);
DIArray RetainTypes = getOrCreateArray(AllRetainTypes);
DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes);
DIArray SPs = getOrCreateArray(AllSubprograms);
DIType(TempSubprograms).replaceAllUsesWith(SPs);
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
DISubprogram SP(SPs.getElement(i));
if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) {
SmallVector<Value *, 4> Variables;
for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii)
Variables.push_back(NMD->getOperand(ii));
if (MDNode *Temp = SP.getVariablesNodes()) {
DIArray AV = getOrCreateArray(Variables);
DIType(Temp).replaceAllUsesWith(AV);
}
NMD->eraseFromParent();
}
}
DIArray GVs = getOrCreateArray(AllGVs);
DIType(TempGVs).replaceAllUsesWith(GVs);
}
/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return
/// N.
static MDNode *getNonCompileUnitScope(MDNode *N) {
if (DIDescriptor(N).isCompileUnit())
return NULL;
return N;
}
/// createCompileUnit - A CompileUnit provides an anchor for all debugging
/// information generated during this instance of compilation.
void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
StringRef Directory, StringRef Producer,
bool isOptimized, StringRef Flags,
unsigned RunTimeVer) {
assert (Lang <= dwarf::DW_LANG_D && Lang >= dwarf::DW_LANG_C89
&& "Invalid Language tag");
assert (!Filename.empty()
&& "Unable to create compile unit without filename");
Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) };
TempEnumTypes = MDNode::getTemporary(VMContext, TElts);
Value *THElts[] = { TempEnumTypes };
MDNode *EnumHolder = MDNode::get(VMContext, THElts);
TempRetainTypes = MDNode::getTemporary(VMContext, TElts);
Value *TRElts[] = { TempRetainTypes };
MDNode *RetainHolder = MDNode::get(VMContext, TRElts);
TempSubprograms = MDNode::getTemporary(VMContext, TElts);
Value *TSElts[] = { TempSubprograms };
MDNode *SPHolder = MDNode::get(VMContext, TSElts);
TempGVs = MDNode::getTemporary(VMContext, TElts);
Value *TVElts[] = { TempGVs };
MDNode *GVHolder = MDNode::get(VMContext, TVElts);
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
ConstantInt::get(Type::getInt32Ty(VMContext), Lang),
MDString::get(VMContext, Filename),
MDString::get(VMContext, Directory),
MDString::get(VMContext, Producer),
// Deprecate isMain field.
ConstantInt::get(Type::getInt1Ty(VMContext), true), // isMain
ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
MDString::get(VMContext, Flags),
ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer),
EnumHolder,
RetainHolder,
SPHolder,
GVHolder
};
TheCU = DICompileUnit(MDNode::