Add a way for a frontend to generate more complex dwarf location
authorMike Stump <mrs@apple.com>
Wed, 30 Sep 2009 00:08:22 +0000 (00:08 +0000)
committerMike Stump <mrs@apple.com>
Wed, 30 Sep 2009 00:08:22 +0000 (00:08 +0000)
information.  This allows arbitrary code involving DW_OP_plus_uconst
and DW_OP_deref.  The scheme allows for easy extention to include,
any, or all of the DW_OP_ opcodes.  I thought about just exposing all
of them, but, wasn't sure if people wanted the dwarf opcodes exposed
in the api.  Is that a layering violation?

With this scheme, the entire existing block scheme used by llvm-gcc
can be switched over to the new scheme.  I think that would be
cleaner, as then the compiler specific bits are not present in llvm
proper.  Before the old code can be yanked however, similar code in
clang would have to be removed.

Next up, more testing.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83120 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/DebugInfo.h
lib/Analysis/DebugInfo.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h

index 8082279a251c4782e9a039a6edf7f8855facc5c6..c40cfb2671047d66e16009d605cdc65d3d932223 100644 (file)
@@ -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<Value *, 9> &addr);
+
     /// CreateLexicalBlock - This creates a descriptor for a lexical block
     /// with the specified parent context.
     DILexicalBlock CreateLexicalBlock(DIDescriptor Context);
index 58bee90372d36d67084af4a980e527143e311926..db5a0cbb21476f034f58d972ec9d287de6366f77 100644 (file)
@@ -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<Value *, 9> &addr) {
+  SmallVector<Value *, 9> 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) {
index f667e31569e338aa7cc53c6b89f95317b8ab44f3..8a74a8ee441b02734dca4e1cff1a20c76fa1cc8c 100644 (file)
@@ -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);
index f582f9b8292d050e385ddbc9039f9b5a2b82089c..8899529698dc77ac19c466cf3e317408a6bead16 100644 (file)
@@ -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);