Skip to content

Commit

Permalink
Refactor. Global variables are part of compile unit so let CompileUni…
Browse files Browse the repository at this point in the history
…t create new global variable.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@137621 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Devang Patel committed Aug 15, 2011
1 parent bb0752b commit 6f9d8ff
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 129 deletions.
7 changes: 7 additions & 0 deletions include/llvm/Analysis/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ namespace llvm {
return getFieldAs<DIFile>(3).getFilename();
}

/// isUnsignedDIType - Return true if type encoding is unsigned.
bool isUnsignedDIType();

/// replaceAllUsesWith - Replace all uses of debug info referenced by
/// this descriptor.
void replaceAllUsesWith(DIDescriptor &D);
Expand Down Expand Up @@ -714,6 +717,10 @@ namespace llvm {
/// getDICompositeType - Find underlying composite type.
DICompositeType getDICompositeType(DIType T);

/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
bool isSubprogramContext(const MDNode *Context);

/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
/// to hold function specific information.
NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, StringRef Name);
Expand Down
30 changes: 30 additions & 0 deletions lib/Analysis/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,22 @@ void DIType::replaceAllUsesWith(MDNode *D) {
}
}

/// isUnsignedDIType - Return true if type encoding is unsigned.
bool DIType::isUnsignedDIType() {
DIDerivedType DTy(DbgNode);
if (DTy.Verify())
return DTy.getTypeDerivedFrom().isUnsignedDIType();

DIBasicType BTy(DbgNode);
if (BTy.Verify()) {
unsigned Encoding = BTy.getEncoding();
if (Encoding == dwarf::DW_ATE_unsigned ||
Encoding == dwarf::DW_ATE_unsigned_char)
return true;
}
return false;
}

/// Verify - Verify that a compile unit is well formed.
bool DICompileUnit::Verify() const {
if (!DbgNode)
Expand Down Expand Up @@ -1014,3 +1030,17 @@ DICompositeType llvm::getDICompositeType(DIType T) {

return DICompositeType();
}

/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
bool llvm::isSubprogramContext(const MDNode *Context) {
if (!Context)
return false;
DIDescriptor D(Context);
if (D.isSubprogram())
return true;
if (D.isType())
return isSubprogramContext(DIType(Context).getContext());
return false;
}

109 changes: 109 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
#include "DwarfCompileUnit.h"
#include "DwarfDebug.h"
#include "llvm/Constants.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/DIBuilder.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
Expand Down Expand Up @@ -994,6 +997,112 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
return SPDie;
}

// Return const expression if value is a GEP to access merged global
// constant. e.g.
// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0)
static const ConstantExpr *getMergedGlobalExpr(const Value *V) {
const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V);
if (!CE || CE->getNumOperands() != 3 ||
CE->getOpcode() != Instruction::GetElementPtr)
return NULL;

// First operand points to a global struct.
Value *Ptr = CE->getOperand(0);
if (!isa<GlobalValue>(Ptr) ||
!isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType()))
return NULL;

// Second operand is zero.
const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
if (!CI || !CI->isZero())
return NULL;

// Third operand is offset.
if (!isa<ConstantInt>(CE->getOperand(2)))
return NULL;

return CE;
}

/// createGlobalVariableDIE - create global variable DIE.
void CompileUnit::createGlobalVariableDIE(const MDNode *N) {
DIGlobalVariable GV(N);

// Check for pre-existence.
if (getDIE(GV))
return;

DIType GTy = GV.getType();
DIE *VariableDIE = new DIE(GV.getTag());

bool isGlobalVariable = GV.getGlobal() != NULL;

// Add name.
addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
StringRef LinkageName = GV.getLinkageName();
if (!LinkageName.empty() && isGlobalVariable)
addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name,
dwarf::DW_FORM_string,
getRealLinkageName(LinkageName));
// Add type.
addType(VariableDIE, GTy);

// Add scoping info.
if (!GV.isLocalToUnit()) {
addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
// Expose as global.
addGlobal(GV.getName(), VariableDIE);
}
// Add line number info.
addSourceLine(VariableDIE, GV);
// Add to map.
insertDIE(N, VariableDIE);
// Add to context owner.
DIDescriptor GVContext = GV.getContext();
addToContextOwner(VariableDIE, GVContext);
// Add location.
if (isGlobalVariable) {
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getSymbol(GV.getGlobal()));
// Do not create specification DIE if context is either compile unit
// or a subprogram.
if (GV.isDefinition() && !GVContext.isCompileUnit() &&
!GVContext.isFile() && !isSubprogramContext(GVContext)) {
// Create specification DIE.
DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
dwarf::DW_FORM_ref4, VariableDIE);
addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag,
1);
addDie(VariableSpecDIE);
} else {
addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
}
} else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV.getConstant()))
addConstantValue(VariableDIE, CI, GTy.isUnsignedDIType());
else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) {
// GV is a merged global.
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
Value *Ptr = CE->getOperand(0);
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
addLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getSymbol(cast<GlobalValue>(Ptr)));
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SmallVector<Value*, 3> Idx(CE->op_begin()+1, CE->op_end());
addUInt(Block, 0, dwarf::DW_FORM_udata,
Asm->getTargetData().getIndexedOffset(Ptr->getType(), Idx));
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
}

return;
}

/// constructSubrangeDIE - Construct subrange DIE from DISubrange.
void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){
DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type);
Expand Down
3 changes: 3 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ class CompileUnit {
/// information entry.
DIEEntry *createDIEEntry(DIE *Entry);

/// createGlobalVariableDIE - create global variable DIE.
void createGlobalVariableDIE(const MDNode *N);

void addPubTypes(DISubprogram SP);

/// constructTypeDIE - Construct basic type die from DIBasicType.
Expand Down
131 changes: 2 additions & 129 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
Expand Down Expand Up @@ -179,19 +178,6 @@ static StringRef getRealLinkageName(StringRef LinkageName) {
return LinkageName;
}

/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
static bool isSubprogramContext(const MDNode *Context) {
if (!Context)
return false;
DIDescriptor D(Context);
if (D.isSubprogram())
return true;
if (D.isType())
return isSubprogramContext(DIType(Context).getContext());
return false;
}

/// updateSubprogramScopeDIE - Find DIE for the given subprogram and
/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes.
/// If there are global variables in this scope then create and insert
Expand Down Expand Up @@ -385,22 +371,6 @@ DIE *DwarfDebug::constructInlinedScopeDIE(LexicalScope *Scope) {
return ScopeDIE;
}

/// isUnsignedDIType - Return true if type encoding is unsigned.
static bool isUnsignedDIType(DIType Ty) {
DIDerivedType DTy(Ty);
if (DTy.Verify())
return isUnsignedDIType(DTy.getTypeDerivedFrom());

DIBasicType BTy(Ty);
if (BTy.Verify()) {
unsigned Encoding = BTy.getEncoding();
if (Encoding == dwarf::DW_ATE_unsigned ||
Encoding == dwarf::DW_ATE_unsigned_char)
return true;
}
return false;
}

/// constructVariableDIE - Construct a DIE for the given DbgVariable.
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, LexicalScope *Scope) {
StringRef Name = DV->getName();
Expand Down Expand Up @@ -504,7 +474,7 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, LexicalScope *Scope) {
updated =
VariableCU->addConstantValue(VariableDie,
DVInsn->getOperand(0).getCImm(),
isUnsignedDIType(DV->getType()));
DV->getType().isUnsignedDIType());
} else {
VariableCU->addVariableAddress(DV, VariableDie,
Asm->getDebugValueLocation(DVInsn));
Expand Down Expand Up @@ -701,33 +671,6 @@ CompileUnit *DwarfDebug::getCompileUnit(const MDNode *N) const {
return I->second;
}

// Return const expression if value is a GEP to access merged global
// constant. e.g.
// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0)
static const ConstantExpr *getMergedGlobalExpr(const Value *V) {
const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V);
if (!CE || CE->getNumOperands() != 3 ||
CE->getOpcode() != Instruction::GetElementPtr)
return NULL;

// First operand points to a global struct.
Value *Ptr = CE->getOperand(0);
if (!isa<GlobalValue>(Ptr) ||
!isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType()))
return NULL;

// Second operand is zero.
const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
if (!CI || !CI->isZero())
return NULL;

// Third operand is offset.
if (!isa<ConstantInt>(CE->getOperand(2)))
return NULL;

return CE;
}

/// constructGlobalVariableDIE - Construct global variable DIE.
void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) {
DIGlobalVariable GV(N);
Expand All @@ -738,77 +681,7 @@ void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) {

// Check for pre-existence.
CompileUnit *TheCU = getCompileUnit(N);
if (TheCU->getDIE(GV))
return;

DIType GTy = GV.getType();
DIE *VariableDIE = new DIE(GV.getTag());

bool isGlobalVariable = GV.getGlobal() != NULL;

// Add name.
TheCU->addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string,
GV.getDisplayName());
StringRef LinkageName = GV.getLinkageName();
if (!LinkageName.empty() && isGlobalVariable)
TheCU->addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name,
dwarf::DW_FORM_string,
getRealLinkageName(LinkageName));
// Add type.
TheCU->addType(VariableDIE, GTy);

// Add scoping info.
if (!GV.isLocalToUnit()) {
TheCU->addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
// Expose as global.
TheCU->addGlobal(GV.getName(), VariableDIE);
}
// Add line number info.
TheCU->addSourceLine(VariableDIE, GV);
// Add to map.
TheCU->insertDIE(N, VariableDIE);
// Add to context owner.
DIDescriptor GVContext = GV.getContext();
TheCU->addToContextOwner(VariableDIE, GVContext);
// Add location.
if (isGlobalVariable) {
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getSymbol(GV.getGlobal()));
// Do not create specification DIE if context is either compile unit
// or a subprogram.
if (GV.isDefinition() && !GVContext.isCompileUnit() &&
!GVContext.isFile() && !isSubprogramContext(GVContext)) {
// Create specification DIE.
DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable);
TheCU->addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
dwarf::DW_FORM_ref4, VariableDIE);
TheCU->addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
TheCU->addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag,
1);
TheCU->addDie(VariableSpecDIE);
} else {
TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
}
} else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV.getConstant()))
TheCU->addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy));
else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) {
// GV is a merged global.
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
Value *Ptr = CE->getOperand(0);
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata,
Asm->Mang->getSymbol(cast<GlobalValue>(Ptr)));
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SmallVector<Value*, 3> Idx(CE->op_begin()+1, CE->op_end());
TheCU->addUInt(Block, 0, dwarf::DW_FORM_udata,
Asm->getTargetData().getIndexedOffset(Ptr->getType(), Idx));
TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
}

TheCU->createGlobalVariableDIE(N);
return;
}

Expand Down

0 comments on commit 6f9d8ff

Please sign in to comment.