diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index 8082279a251..c40cfb26710 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -187,10 +187,10 @@ namespace llvm { class DIType : public DIDescriptor { public: enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, FlagBlockByrefStruct = 1 << 4 }; @@ -409,6 +409,17 @@ namespace llvm { /// Verify - Verify that a variable descriptor is well formed. bool Verify() const; + /// HasComplexAddr - Return true if the variable has a complex address. + bool hasComplexAddress() const { + return getNumAddrElements() > 0; + } + + unsigned getNumAddrElements() const { return DbgNode->getNumElements()-6; } + + uint64_t getAddrElement(unsigned Idx) const { + return getUInt64Field(Idx+6); + } + /// isBlockByrefVariable - Return true if the variable was declared as /// a "__block" variable (Apple Blocks). bool isBlockByrefVariable() const { @@ -463,6 +474,8 @@ namespace llvm { DIFactory(const DIFactory &); // DO NOT IMPLEMENT void operator=(const DIFactory&); // DO NOT IMPLEMENT public: + enum ComplexAddrKind { OpPlus=1, OpDeref }; + explicit DIFactory(Module &m); /// GetOrCreateArray - Create an descriptor for an array of descriptors. @@ -540,6 +553,14 @@ namespace llvm { DICompileUnit CompileUnit, unsigned LineNo, DIType Type); + /// CreateComplexVariable - Create a new descriptor for the specified + /// variable which has a complex address expression for its address. + DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Context, + const std::string &Name, + DICompileUnit CompileUnit, unsigned LineNo, + DIType Type, + SmallVector &addr); + /// CreateLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. DILexicalBlock CreateLexicalBlock(DIDescriptor Context); diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp index 58bee90372d..db5a0cbb214 100644 --- a/lib/Analysis/DebugInfo.cpp +++ b/lib/Analysis/DebugInfo.cpp @@ -531,6 +531,8 @@ void DIVariable::dump() const { errs() << " [" << getLineNumber() << "] "; getType().dump(); errs() << "\n"; + + // FIXME: Dump complex addresses } //===----------------------------------------------------------------------===// @@ -781,6 +783,26 @@ DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, } +/// CreateComplexVariable - Create a new descriptor for the specified variable +/// which has a complex address expression for its address. +DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, + const std::string &Name, + DICompileUnit CompileUnit, + unsigned LineNo, + DIType Type, SmallVector &addr) { + SmallVector Elts; + Elts.push_back(GetTagConstant(Tag)); + Elts.push_back(Context.getNode()); + Elts.push_back(MDString::get(VMContext, Name)); + Elts.push_back(CompileUnit.getNode()); + Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); + Elts.push_back(Type.getNode()); + Elts.insert(Elts.end(), addr.begin(), addr.end()); + + return DIVariable(MDNode::get(VMContext, &Elts[0], 6+addr.size())); +} + + /// CreateBlock - This creates a descriptor for a lexical block with the /// specified parent VMContext. DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) { diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f667e31569e..8a74a8ee441 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -556,7 +556,7 @@ DIType DwarfDebug::GetBlockByrefType(DIType Ty, std::string Name) { unsigned tag = Ty.getTag(); if (tag == dwarf::DW_TAG_pointer_type) { - DIDerivedType DTy = DIDerivedType (Ty.getNode()); + DIDerivedType DTy = DIDerivedType(Ty.getNode()); subType = DTy.getTypeDerivedFrom(); } @@ -577,6 +577,56 @@ DIType DwarfDebug::GetBlockByrefType(DIType Ty, std::string Name) { return Ty; } +/// AddComplexAddress - Start with the address based on the location provided, +/// and generate the DWARF information necessary to find the actual variable +/// given the extra address information encoded in the DIVariable, starting from +/// the starting location. Add the DWARF information to the die. +/// +void DwarfDebug::AddComplexAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + const DIVariable &VD = DV->getVariable(); + DIType Ty = VD.getType(); + + // Decode the original location, and use that as the start of the byref + // variable's location. + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + Reg = Reg - dwarf::DW_OP_reg0; + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + AddUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + AddUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + for (unsigned i = 0, N = VD.getNumAddrElements(); i < N; ++i) { + uint64_t Element = VD.getAddrElement(i); + + if (Element == DIFactory::OpPlus) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + AddUInt(Block, 0, dwarf::DW_FORM_udata, VD.getAddrElement(++i)); + } else if (Element == DIFactory::OpDeref) { + AddUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } else llvm_unreachable("unknown DIFactory Opcode"); + } + + // Now attach the location information to the DIE. + AddBlock(Die, Attribute, 0, Block); +} + /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName either the struct, or a pointer to the struct, as @@ -649,7 +699,7 @@ void DwarfDebug::AddBlockByrefAddress(DbgVariable *&DV, DIE *Die, const char *varName = VD.getName(); if (Tag == dwarf::DW_TAG_pointer_type) { - DIDerivedType DTy = DIDerivedType (Ty.getNode()); + DIDerivedType DTy = DIDerivedType(Ty.getNode()); TmpTy = DTy.getTypeDerivedFrom(); isPointer = true; } @@ -790,7 +840,6 @@ void DwarfDebug::AddType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) { else { assert(Ty.isDerivedType() && "Unknown kind of DIType"); ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getNode())); - } // Add debug information entry to entity and appropriate context. @@ -1187,6 +1236,7 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { AddSourceLine(VariableDie, &VD); // Add variable type. + // FIXME: isBlockByrefVariable should be reformulated in terms of complex addresses instead. if (VD.isBlockByrefVariable()) AddType(Unit, VariableDie, GetBlockByrefType(VD.getType(), Name)); else @@ -1200,7 +1250,10 @@ DIE *DwarfDebug::CreateDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) { Location.set(RI->getFrameRegister(*MF), RI->getFrameIndexOffset(*MF, DV->getFrameIndex())); - if (VD.isBlockByrefVariable()) + + if (VD.hasComplexAddress()) + AddComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location); + else if (VD.isBlockByrefVariable()) AddBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location); else AddAddress(VariableDie, dwarf::DW_AT_location, Location); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index f582f9b8292..8899529698d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -284,10 +284,20 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { void AddAddress(DIE *Die, unsigned Attribute, const MachineLocation &Location); + /// AddComplexAddress - Start with the address based on the location provided, + /// and generate the DWARF information necessary to find the actual variable + /// (navigating the extra location information encoded in the type) based on + /// the starting location. Add the DWARF information to the die. + /// + void AddComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + // FIXME: Should be reformulated in terms of AddComplexAddress. /// AddBlockByrefAddress - Start with the address based on the location /// provided, and generate the DWARF information necessary to find the /// actual Block variable (navigating the Block struct) based on the - /// starting location. Add the DWARF information to the die. + /// starting location. Add the DWARF information to the die. Obsolete, + /// please use AddComplexAddress instead. /// void AddBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, const MachineLocation &Location); @@ -459,8 +469,9 @@ class VISIBILITY_HIDDEN DwarfDebug : public Dwarf { void ConstructSubprogram(MDNode *N); + // FIXME: This should go away in favor of complex addresses. /// Find the type the programmer originally declared the variable to be - /// and return that type. + /// and return that type. Obsolete, use GetComplexAddrType instead. /// DIType GetBlockByrefType(DIType Ty, std::string Name);