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
};
/// 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 {
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.
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);
errs() << " [" << getLineNumber() << "] ";
getType().dump();
errs() << "\n";
+
+ // FIXME: Dump complex addresses
}
//===----------------------------------------------------------------------===//
}
+/// 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) {
unsigned tag = Ty.getTag();
if (tag == dwarf::DW_TAG_pointer_type) {
- DIDerivedType DTy = DIDerivedType (Ty.getNode());
+ DIDerivedType DTy = DIDerivedType(Ty.getNode());
subType = DTy.getTypeDerivedFrom();
}
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
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;
}
else {
assert(Ty.isDerivedType() && "Unknown kind of DIType");
ConstructTypeDIE(DW_Unit, Buffer, DIDerivedType(Ty.getNode()));
-
}
// Add debug information entry to entity and appropriate context.
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
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);
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);
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);