- /// ConstructType - Adds all the required attributes to the type.
- ///
- void ConstructType(DIE &Buffer, TypeDesc *TyDesc, CompileUnit *Unit) {
- // Get core information.
- const std::string &Name = TyDesc->getName();
- uint64_t Size = TyDesc->getSize() >> 3;
-
- if (BasicTypeDesc *BasicTy = dyn_cast<BasicTypeDesc>(TyDesc)) {
- // Fundamental types like int, float, bool
- Buffer.setTag(DW_TAG_base_type);
- AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, BasicTy->getEncoding());
- } else if (DerivedTypeDesc *DerivedTy = dyn_cast<DerivedTypeDesc>(TyDesc)) {
- // Fetch tag.
- unsigned Tag = DerivedTy->getTag();
- // FIXME - Workaround for templates.
- if (Tag == DW_TAG_inheritance) Tag = DW_TAG_reference_type;
- // Pointers, typedefs et al.
- Buffer.setTag(Tag);
- // Map to main type, void will not have a type.
- if (TypeDesc *FromTy = DerivedTy->getFromType())
- AddType(&Buffer, FromTy, Unit);
- } else if (CompositeTypeDesc *CompTy = dyn_cast<CompositeTypeDesc>(TyDesc)){
- // Fetch tag.
- unsigned Tag = CompTy->getTag();
-
- // Set tag accordingly.
- if (Tag == DW_TAG_vector_type)
- Buffer.setTag(DW_TAG_array_type);
- else
- Buffer.setTag(Tag);
-
- std::vector<DebugInfoDesc *> &Elements = CompTy->getElements();
-
- switch (Tag) {
- case DW_TAG_vector_type:
- AddUInt(&Buffer, DW_AT_GNU_vector, DW_FORM_flag, 1);
- // Fall thru
- case DW_TAG_array_type: {
- // Add element type.
- if (TypeDesc *FromTy = CompTy->getFromType())
- AddType(&Buffer, FromTy, Unit);
-
- // Don't emit size attribute.
- Size = 0;
-
- // Construct an anonymous type for index type.
- DIE Buffer(DW_TAG_base_type);
- AddUInt(&Buffer, DW_AT_byte_size, 0, sizeof(int32_t));
- AddUInt(&Buffer, DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
- DIE *IndexTy = Unit->AddDie(Buffer);
-
- // Add subranges to array type.
- for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
- SubrangeDesc *SRD = cast<SubrangeDesc>(Elements[i]);
- int64_t Lo = SRD->getLo();
- int64_t Hi = SRD->getHi();
- DIE *Subrange = new DIE(DW_TAG_subrange_type);
-
- // If a range is available.
- if (Lo != Hi) {
- AddDIEntry(Subrange, DW_AT_type, DW_FORM_ref4, IndexTy);
- // Only add low if non-zero.
- if (Lo) AddSInt(Subrange, DW_AT_lower_bound, 0, Lo);
- AddSInt(Subrange, DW_AT_upper_bound, 0, Hi);
- }
-
- Buffer.AddChild(Subrange);
- }
- break;
- }
- case DW_TAG_structure_type:
- case DW_TAG_union_type: {
- // Add elements to structure type.
- for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
- DebugInfoDesc *Element = Elements[i];
-
- if (DerivedTypeDesc *MemberDesc = dyn_cast<DerivedTypeDesc>(Element)){
- // Add field or base class.
- unsigned Tag = MemberDesc->getTag();
-
- // Extract the basic information.
- const std::string &Name = MemberDesc->getName();
- uint64_t Size = MemberDesc->getSize();
- uint64_t Align = MemberDesc->getAlign();
- uint64_t Offset = MemberDesc->getOffset();
-
- // Construct member debug information entry.
- DIE *Member = new DIE(Tag);
-
- // Add name if not "".
- if (!Name.empty())
- AddString(Member, DW_AT_name, DW_FORM_string, Name);
-
- // Add location if available.
- AddSourceLine(Member, MemberDesc->getFile(), MemberDesc->getLine());
-
- // Most of the time the field info is the same as the members.
- uint64_t FieldSize = Size;
- uint64_t FieldAlign = Align;
- uint64_t FieldOffset = Offset;
-
- // Set the member type.
- TypeDesc *FromTy = MemberDesc->getFromType();
- AddType(Member, FromTy, Unit);
-
- // Walk up typedefs until a real size is found.
- while (FromTy) {
- if (FromTy->getTag() != DW_TAG_typedef) {
- FieldSize = FromTy->getSize();
- FieldAlign = FromTy->getAlign();
- break;
- }
-
- FromTy = cast<DerivedTypeDesc>(FromTy)->getFromType();
- }
-
- // Unless we have a bit field.
- if (Tag == DW_TAG_member && FieldSize != Size) {
- // Construct the alignment mask.
- uint64_t AlignMask = ~(FieldAlign - 1);
- // Determine the high bit + 1 of the declared size.
- uint64_t HiMark = (Offset + FieldSize) & AlignMask;
- // Work backwards to determine the base offset of the field.
- FieldOffset = HiMark - FieldSize;
- // Now normalize offset to the field.
- Offset -= FieldOffset;
-
- // Maybe we need to work from the other end.
- if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
-
- // Add size and offset.
- AddUInt(Member, DW_AT_byte_size, 0, FieldSize >> 3);
- AddUInt(Member, DW_AT_bit_size, 0, Size);
- AddUInt(Member, DW_AT_bit_offset, 0, Offset);
- }
-
- // Add computation for offset.
- DIEBlock *Block = new DIEBlock();
- AddUInt(Block, 0, DW_FORM_data1, DW_OP_plus_uconst);
- AddUInt(Block, 0, DW_FORM_udata, FieldOffset >> 3);
- AddBlock(Member, DW_AT_data_member_location, 0, Block);
-
- // Add accessibility (public default unless is base class.
- if (MemberDesc->isProtected()) {
- AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_protected);
- } else if (MemberDesc->isPrivate()) {
- AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_private);
- } else if (Tag == DW_TAG_inheritance) {
- AddUInt(Member, DW_AT_accessibility, 0, DW_ACCESS_public);
- }
-
- Buffer.AddChild(Member);
- } else if (GlobalVariableDesc *StaticDesc =
- dyn_cast<GlobalVariableDesc>(Element)) {
- // Add static member.
-
- // Construct member debug information entry.
- DIE *Static = new DIE(DW_TAG_variable);
-
- // Add name and mangled name.
- const std::string &Name = StaticDesc->getName();
- const std::string &LinkageName = StaticDesc->getLinkageName();
- AddString(Static, DW_AT_name, DW_FORM_string, Name);
- if (!LinkageName.empty()) {
- AddString(Static, DW_AT_MIPS_linkage_name, DW_FORM_string,
- LinkageName);
- }
-
- // Add location.
- AddSourceLine(Static, StaticDesc->getFile(), StaticDesc->getLine());
-
- // Add type.
- if (TypeDesc *StaticTy = StaticDesc->getType())
- AddType(Static, StaticTy, Unit);
-
- // Add flags.
- if (!StaticDesc->isStatic())
- AddUInt(Static, DW_AT_external, DW_FORM_flag, 1);
- AddUInt(Static, DW_AT_declaration, DW_FORM_flag, 1);
-
- Buffer.AddChild(Static);
- } else if (SubprogramDesc *MethodDesc =
- dyn_cast<SubprogramDesc>(Element)) {
- // Add member function.
-
- // Construct member debug information entry.
- DIE *Method = new DIE(DW_TAG_subprogram);
-
- // Add name and mangled name.
- const std::string &Name = MethodDesc->getName();
- const std::string &LinkageName = MethodDesc->getLinkageName();
-
- AddString(Method, DW_AT_name, DW_FORM_string, Name);
- bool IsCTor = TyDesc->getName() == Name;
-
- if (!LinkageName.empty()) {
- AddString(Method, DW_AT_MIPS_linkage_name, DW_FORM_string,
- LinkageName);
- }
-
- // Add location.
- AddSourceLine(Method, MethodDesc->getFile(), MethodDesc->getLine());
-
- // Add type.
- if (CompositeTypeDesc *MethodTy =
- dyn_cast_or_null<CompositeTypeDesc>(MethodDesc->getType())) {
- // Get argument information.
- std::vector<DebugInfoDesc *> &Args = MethodTy->getElements();
-
- // If not a ctor.
- if (!IsCTor) {
- // Add return type.
- AddType(Method, dyn_cast<TypeDesc>(Args[0]), Unit);
- }
-
- // Add arguments.
- for (unsigned i = 1, N = Args.size(); i < N; ++i) {
- DIE *Arg = new DIE(DW_TAG_formal_parameter);
- AddType(Arg, cast<TypeDesc>(Args[i]), Unit);
- AddUInt(Arg, DW_AT_artificial, DW_FORM_flag, 1);
- Method->AddChild(Arg);
- }
- }
-
- // Add flags.
- if (!MethodDesc->isStatic())
- AddUInt(Method, DW_AT_external, DW_FORM_flag, 1);
- AddUInt(Method, DW_AT_declaration, DW_FORM_flag, 1);
-
- Buffer.AddChild(Method);
- }
- }
- break;
- }
- case DW_TAG_enumeration_type: {
- // Add enumerators to enumeration type.
- for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
- EnumeratorDesc *ED = cast<EnumeratorDesc>(Elements[i]);
- const std::string &Name = ED->getName();
- int64_t Value = ED->getValue();
- DIE *Enumerator = new DIE(DW_TAG_enumerator);
- AddString(Enumerator, DW_AT_name, DW_FORM_string, Name);
- AddSInt(Enumerator, DW_AT_const_value, DW_FORM_sdata, Value);
- Buffer.AddChild(Enumerator);
- }
-
- break;
- }
- case DW_TAG_subroutine_type: {
- // Add prototype flag.
- AddUInt(&Buffer, DW_AT_prototyped, DW_FORM_flag, 1);
- // Add return type.
- AddType(&Buffer, dyn_cast<TypeDesc>(Elements[0]), Unit);
-
- // Add arguments.
- for (unsigned i = 1, N = Elements.size(); i < N; ++i) {
- DIE *Arg = new DIE(DW_TAG_formal_parameter);
- AddType(Arg, cast<TypeDesc>(Elements[i]), Unit);
- Buffer.AddChild(Arg);
- }
-
- break;
- }
- default: break;
- }
- }
-
- // Add name if not anonymous or intermediate type.
- if (!Name.empty()) AddString(&Buffer, DW_AT_name, DW_FORM_string, Name);