/// getOriginalTypeSize - If this type is derived from a base type then /// return base type size. uint64_t DIDerivedType::getOriginalTypeSize() const { unsigned Tag = getTag(); if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type) return getSizeInBits(); DIType BaseType = getTypeDerivedFrom(); // If this type is not derived from any type then take conservative approach. if (!BaseType.isValid()) return getSizeInBits(); // If this is a derived type, go ahead and get the base type, unless it's a // reference then it's just the size of the field. Pointer types have no need // of this since they're a different type of qualification on the type. if (BaseType.getTag() == dwarf::DW_TAG_reference_type || BaseType.getTag() == dwarf::DW_TAG_rvalue_reference_type) return getSizeInBits(); if (BaseType.isDerivedType()) return DIDerivedType(BaseType).getOriginalTypeSize(); return BaseType.getSizeInBits(); }
/// PopulateDebugInfo - Populate the TypeNo, Aux[] and TagName from Ty. /// void PIC16DbgInfo::PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { if (Ty.isBasicType(Ty.getTag())) PopulateBasicTypeInfo (Ty, TypeNo); else if (Ty.isDerivedType(Ty.getTag())) PopulateDerivedTypeInfo (Ty, TypeNo, HasAux, Aux, TagName); else if (Ty.isCompositeType(Ty.getTag())) PopulateCompositeTypeInfo (Ty, TypeNo, HasAux, Aux, TagName); else { TypeNo = PIC16Dbg::T_NULL; HasAux = false; } return; }
/// If this type is derived from a base type then return base type size. uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) { DIType *Ty = TyRef.resolve(); assert(Ty); DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty); if (!DDTy) return Ty->getSizeInBits(); unsigned Tag = DDTy->getTag(); if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type) return DDTy->getSizeInBits(); DIType *BaseType = DDTy->getBaseType().resolve(); assert(BaseType && "Unexpected invalid base type"); // If this is a derived type, go ahead and get the base type, unless it's a // reference then it's just the size of the field. Pointer types have no need // of this since they're a different type of qualification on the type. if (BaseType->getTag() == dwarf::DW_TAG_reference_type || BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type) return Ty->getSizeInBits(); return getBaseTypeSize(BaseType); }
/// PopulateDerivedTypeInfo - Populate TypeNo, Aux[], TagName for derived type /// from Ty. Derived types are mostly pointers. /// void PIC16DbgInfo::PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { switch(Ty.getTag()) { case dwarf::DW_TAG_pointer_type: TypeNo = TypeNo << PIC16Dbg::S_DERIVED; TypeNo = TypeNo | PIC16Dbg::DT_PTR; break; default: TypeNo = TypeNo << PIC16Dbg::S_DERIVED; } // We also need to encode the the information about the base type of // pointer in TypeNo. DIType BaseType = DIDerivedType(Ty.getGV()).getTypeDerivedFrom(); PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName); }
/// 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. For /// more information, read large comment just above here. /// void CompileUnit::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, const MachineLocation &Location) { DIType Ty = DV->getType(); DIType TmpTy = Ty; unsigned Tag = Ty.getTag(); bool isPointer = false; StringRef varName = DV->getName(); if (Tag == dwarf::DW_TAG_pointer_type) { DIDerivedType DTy = DIDerivedType(Ty); TmpTy = DTy.getTypeDerivedFrom(); isPointer = true; } DICompositeType blockStruct = DICompositeType(TmpTy); // Find the __forwarding field and the variable field in the __Block_byref // struct. DIArray Fields = blockStruct.getTypeArray(); DIDescriptor varField = DIDescriptor(); DIDescriptor forwardingField = DIDescriptor(); for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { DIDescriptor Element = Fields.getElement(i); DIDerivedType DT = DIDerivedType(Element); StringRef fieldName = DT.getName(); if (fieldName == "__forwarding") forwardingField = Element; else if (fieldName == varName) varField = Element; } // Get the offsets for the forwarding field and the variable field. unsigned forwardingFieldOffset = DIDerivedType(forwardingField).getOffsetInBits() >> 3; unsigned varFieldOffset = DIDerivedType(varField).getOffsetInBits() >> 3; // Decode the original location, and use that as the start of the byref // variable's location. const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); if (Location.isReg()) { if (Reg < 32) addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); else { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); 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()); } // If we started with a pointer to the __Block_byref... struct, then // the first thing we need to do is dereference the pointer (DW_OP_deref). if (isPointer) addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Next add the offset for the '__forwarding' field: // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in // adding the offset if it's 0. if (forwardingFieldOffset > 0) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); } // Now dereference the __forwarding field to get to the real __Block_byref // struct: DW_OP_deref. addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Now that we've got the real __Block_byref... struct, add the offset // for the variable's field to get to the location of the actual variable: // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. if (varFieldOffset > 0) { addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); } // Now attach the location information to the DIE. addBlock(Die, Attribute, 0, Block); }