#include "llvm/Support/Dwarf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Mangler.h"
+#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
static cl::opt<bool>
DwarfVerbose("dwarf-verbose", cl::Hidden,
- cl::desc("Add comments to Dwarf directives."));
+ cl::desc("Add comments to Dwarf directives."));
namespace llvm {
}
#ifndef NDEBUG
- void DIEAbbrev::print(std::ostream &O) {
- O << "Abbreviation @"
- << std::hex << (intptr_t)this << std::dec
+void DIEAbbrev::print(std::ostream &O) {
+ O << "Abbreviation @"
+ << std::hex << (intptr_t)this << std::dec
+ << " "
+ << TagString(Tag)
+ << " "
+ << ChildrenString(ChildrenFlag)
+ << "\n";
+
+ for (unsigned i = 0, N = Data.size(); i < N; ++i) {
+ O << " "
+ << AttributeString(Data[i].getAttribute())
<< " "
- << TagString(Tag)
- << " "
- << ChildrenString(ChildrenFlag)
+ << FormEncodingString(Data[i].getForm())
<< "\n";
-
- for (unsigned i = 0, N = Data.size(); i < N; ++i) {
- O << " "
- << AttributeString(Data[i].getAttribute())
- << " "
- << FormEncodingString(Data[i].getForm())
- << "\n";
- }
}
- void DIEAbbrev::dump() { print(std::cerr); }
+}
+void DIEAbbrev::dump() { print(std::cerr); }
#endif
//===----------------------------------------------------------------------===//
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEDwarfLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
- return DW.getAddressSize();
+ return DW.getTargetAsmInfo()->getAddressSize();
}
//===----------------------------------------------------------------------===//
/// SizeOf - Determine size of label value in bytes.
///
unsigned DIEObjectLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
- return DW.getAddressSize();
+ return DW.getTargetAsmInfo()->getAddressSize();
}
//===----------------------------------------------------------------------===//
/// SizeOf - Determine size of delta value in bytes.
///
unsigned DIEDelta::SizeOf(const DwarfWriter &DW, unsigned Form) const {
- return DW.getAddressSize();
+ return DW.getTargetAsmInfo()->getAddressSize();
}
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
-/// DWContext
+/// DwarfWriter
//===----------------------------------------------------------------------===//
void DwarfWriter::EOL(const std::string &Comment) const {
if (DwarfVerbose && !Comment.empty()) {
O << "\t"
- << Asm->CommentString
+ << TAI->getCommentString()
<< " "
<< Comment;
}
/// EmitAlign - Print a align directive.
///
void DwarfWriter::EmitAlign(unsigned Alignment) const {
- O << Asm->AlignDirective << Alignment << "\n";
+ O << TAI->getAlignDirective() << Alignment << "\n";
}
/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
/// unsigned leb128 value.
void DwarfWriter::EmitULEB128Bytes(unsigned Value) const {
- if (hasLEB128) {
+ if (TAI->hasLEB128()) {
O << "\t.uleb128\t"
<< Value;
} else {
- O << Asm->Data8bitsDirective;
+ O << TAI->getData8bitsDirective();
PrintULEB128(Value);
}
}
/// EmitSLEB128Bytes - Emit an assembler byte data directive to compose a
/// signed leb128 value.
void DwarfWriter::EmitSLEB128Bytes(int Value) const {
- if (hasLEB128) {
+ if (TAI->hasLEB128()) {
O << "\t.sleb128\t"
<< Value;
} else {
- O << Asm->Data8bitsDirective;
+ O << TAI->getData8bitsDirective();
PrintSLEB128(Value);
}
}
/// EmitInt8 - Emit a byte directive and value.
///
void DwarfWriter::EmitInt8(int Value) const {
- O << Asm->Data8bitsDirective;
+ O << TAI->getData8bitsDirective();
PrintHex(Value & 0xFF);
}
/// EmitInt16 - Emit a short directive and value.
///
void DwarfWriter::EmitInt16(int Value) const {
- O << Asm->Data16bitsDirective;
+ O << TAI->getData16bitsDirective();
PrintHex(Value & 0xFFFF);
}
/// EmitInt32 - Emit a long directive and value.
///
void DwarfWriter::EmitInt32(int Value) const {
- O << Asm->Data32bitsDirective;
+ O << TAI->getData32bitsDirective();
PrintHex(Value);
}
/// EmitInt64 - Emit a long long directive and value.
///
void DwarfWriter::EmitInt64(uint64_t Value) const {
- if (Asm->Data64bitsDirective) {
- O << Asm->Data64bitsDirective << "0x" << std::hex << Value << std::dec;
+ if (TAI->getData64bitsDirective()) {
+ O << TAI->getData64bitsDirective() << "0x" << std::hex << Value << std::dec;
} else {
if (TD->isBigEndian()) {
EmitInt32(unsigned(Value >> 32)); O << "\n";
/// EmitString - Emit a string with quotes and a null terminator.
/// Special characters are emitted properly. (Eg. '\t')
void DwarfWriter::EmitString(const std::string &String) const {
- O << Asm->AsciiDirective
+ O << TAI->getAsciiDirective()
<< "\"";
for (unsigned i = 0, N = String.size(); i < N; ++i) {
unsigned char C = String[i];
case '\t': O << "\\t"; break;
default:
O << '\\';
- O << char('0' + (C >> 6));
- O << char('0' + (C >> 3));
- O << char('0' + (C >> 0));
+ O << char('0' + ((C >> 6) & 7));
+ O << char('0' + ((C >> 3) & 7));
+ O << char('0' + ((C >> 0) & 7));
break;
}
} else if (C == '\"') {
/// PrintLabelName - Print label name in form used by Dwarf writer.
///
void DwarfWriter::PrintLabelName(const char *Tag, unsigned Number) const {
- O << Asm->PrivateGlobalPrefix
+ O << TAI->getPrivateGlobalPrefix()
<< "debug_"
<< Tag;
if (Number) O << Number;
/// EmitReference - Emit a reference to a label.
///
void DwarfWriter::EmitReference(const char *Tag, unsigned Number) const {
- if (AddressSize == 4)
- O << Asm->Data32bitsDirective;
+ if (TAI->getAddressSize() == 4)
+ O << TAI->getData32bitsDirective();
else
- O << Asm->Data64bitsDirective;
+ O << TAI->getData64bitsDirective();
PrintLabelName(Tag, Number);
}
void DwarfWriter::EmitReference(const std::string &Name) const {
- if (AddressSize == 4)
- O << Asm->Data32bitsDirective;
+ if (TAI->getAddressSize() == 4)
+ O << TAI->getData32bitsDirective();
else
- O << Asm->Data64bitsDirective;
+ O << TAI->getData64bitsDirective();
O << Name;
}
/// is an option (needsSet) to use an intermediary 'set' expression.
void DwarfWriter::EmitDifference(const char *TagHi, unsigned NumberHi,
const char *TagLo, unsigned NumberLo) const {
- if (needsSet) {
+ if (TAI->needsSet()) {
static unsigned SetCounter = 0;
O << "\t.set\t";
PrintLabelName(TagLo, NumberLo);
O << "\n";
- if (AddressSize == sizeof(int32_t))
- O << Asm->Data32bitsDirective;
+ if (TAI->getAddressSize() == sizeof(int32_t))
+ O << TAI->getData32bitsDirective();
else
- O << Asm->Data64bitsDirective;
+ O << TAI->getData64bitsDirective();
PrintLabelName("set", SetCounter);
++SetCounter;
} else {
- if (AddressSize == sizeof(int32_t))
- O << Asm->Data32bitsDirective;
+ if (TAI->getAddressSize() == sizeof(int32_t))
+ O << TAI->getData32bitsDirective();
else
- O << Asm->Data64bitsDirective;
+ O << TAI->getData64bitsDirective();
PrintLabelName(TagHi, NumberHi);
O << "-";
/// AddSourceLine - Add location information to specified debug information
/// entry.
-void DwarfWriter::AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line) {
+void DwarfWriter::AddSourceLine(DIE *Die, CompileUnitDesc *File, unsigned Line){
if (File && Line) {
CompileUnit *FileUnit = FindCompileUnit(File);
unsigned FileID = FileUnit->getID();
void DwarfWriter::AddAddress(DIE *Die, unsigned Attribute,
const MachineLocation &Location) {
DIEBlock *Block = new DIEBlock();
+ unsigned Reg = RI->getDwarfRegNum(Location.getRegister());
+
if (Location.isRegister()) {
- Block->AddUInt(DW_FORM_data1,
- DW_OP_reg0 + RI->getDwarfRegNum(Location.getRegister()));
+ if (Reg < 32) {
+ Block->AddUInt(DW_FORM_data1, DW_OP_reg0 + Reg);
+ } else {
+ Block->AddUInt(DW_FORM_data1, DW_OP_regx);
+ Block->AddUInt(DW_FORM_udata, Reg);
+ }
} else {
- Block->AddUInt(DW_FORM_data1,
- DW_OP_breg0 + RI->getDwarfRegNum(Location.getRegister()));
+ if (Reg < 32) {
+ Block->AddUInt(DW_FORM_data1, DW_OP_breg0 + Reg);
+ } else {
+ Block->AddUInt(DW_FORM_data1, DW_OP_bregx);
+ Block->AddUInt(DW_FORM_udata, Reg);
+ }
Block->AddUInt(DW_FORM_sdata, Location.getOffset());
}
Block->ComputeSize(*this);
DIE *&DwarfWriter::getDieMapSlotFor(DebugInfoDesc *DD) {
return DescToDieMap[DD];
}
-
+
/// NewType - Create a new type DIE.
///
DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc, CompileUnit *Unit) {
return Die;
}
- // FIXME - Should handle other contexts that compile units.
-
// Check for pre-existence.
DIE *&Slot = Unit->getDieMapSlotFor(TyDesc);
if (Slot) return Slot;
// Fundamental types like int, float, bool
Slot = Ty = new DIE(DW_TAG_base_type);
unsigned Encoding = BasicTy->getEncoding();
- Ty->AddUInt (DW_AT_encoding, DW_FORM_data1, Encoding);
+ Ty->AddUInt(DW_AT_encoding, DW_FORM_data1, Encoding);
} else if (DerivedTypeDesc *DerivedTy = dyn_cast<DerivedTypeDesc>(TyDesc)) {
// Create specific DIE.
Slot = Ty = new DIE(DerivedTy->getTag());
NewType(Context, FromTy, Unit));
}
} else if (CompositeTypeDesc *CompTy = dyn_cast<CompositeTypeDesc>(TyDesc)) {
+ // Fetch tag
+ unsigned Tag = CompTy->getTag();
+
// Create specific DIE.
- Slot = Ty = new DIE(CompTy->getTag());
+ Slot = Ty = Tag == DW_TAG_vector_type ? new DIE(DW_TAG_array_type) :
+ new DIE(Tag);
+
std::vector<DebugInfoDesc *> &Elements = CompTy->getElements();
- switch (CompTy->getTag()) {
+ switch (Tag) {
+ case DW_TAG_vector_type: Ty->AddUInt(DW_AT_GNU_vector, DW_FORM_flag, 1);
+ // Fall thru
case DW_TAG_array_type: {
// Add element type.
if (TypeDesc *FromTy = CompTy->getFromType()) {
Ty->AddDIEntry(DW_AT_type, DW_FORM_ref4,
NewType(Context, FromTy, Unit));
}
+
// Don't emit size attribute.
Size = 0;
}
case DW_TAG_structure_type:
case DW_TAG_union_type: {
- // FIXME - this is just the basics.
// Add elements to structure type.
for(unsigned i = 0, N = Elements.size(); i < N; ++i) {
- DerivedTypeDesc *MemberDesc = cast<DerivedTypeDesc>(Elements[i]);
-
- // Extract the basic information.
- const std::string &Name = MemberDesc->getName();
- TypeDesc *MemTy = MemberDesc->getFromType();
- uint64_t Size = MemberDesc->getSize();
- uint64_t Align = MemberDesc->getAlign();
- uint64_t Offset = MemberDesc->getOffset();
-
- // Construct member debug information entry.
- DIE *Member = new DIE(DW_TAG_member);
-
- // Add name if not "".
- if (!Name.empty()) Member->AddString(DW_AT_name, DW_FORM_string, Name);
- // Add location if available.
- AddSourceLine(Member, MemberDesc->getFile(), MemberDesc->getLine());
+ DebugInfoDesc *Element = Elements[i];
- // 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;
-
- if (TypeDesc *FromTy = MemberDesc->getFromType()) {
- Member->AddDIEntry(DW_AT_type, DW_FORM_ref4,
- NewType(Context, FromTy, Unit));
- FieldSize = FromTy->getSize();
- FieldAlign = FromTy->getSize();
- }
+ if (DerivedTypeDesc *MemberDesc = dyn_cast<DerivedTypeDesc>(Element)) {
+ // Add field or base class.
+
+ unsigned Tag = MemberDesc->getTag();
- // Unless we have a bit field.
- if (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;
+ // Extract the basic information.
+ const std::string &Name = MemberDesc->getName();
+ TypeDesc *MemTy = MemberDesc->getFromType();
+ 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())Member->AddString(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;
- // Maybe we need to work from the other end.
- if (TD->isLittleEndian()) Offset = FieldSize - (Offset + Size);
+ if (TypeDesc *FromTy = MemberDesc->getFromType()) {
+ Member->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+ NewType(Context, FromTy, Unit));
+ FieldSize = FromTy->getSize();
+ FieldAlign = FromTy->getSize();
+ }
- Member->AddUInt(DW_AT_byte_size, 0, FieldSize >> 3);
- Member->AddUInt(DW_AT_bit_size, 0, Size);
- Member->AddUInt(DW_AT_bit_offset, 0, Offset);
+ // 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.
+ Member->AddUInt(DW_AT_byte_size, 0, FieldSize >> 3);
+ Member->AddUInt(DW_AT_bit_size, 0, Size);
+ Member->AddUInt(DW_AT_bit_offset, 0, Offset);
+ }
+
+ // Add computation for offset.
+ DIEBlock *Block = new DIEBlock();
+ Block->AddUInt(DW_FORM_data1, DW_OP_plus_uconst);
+ Block->AddUInt(DW_FORM_udata, FieldOffset >> 3);
+ Block->ComputeSize(*this);
+ Member->AddBlock(DW_AT_data_member_location, 0, Block);
+
+ // Add accessibility (public default unless is base class.
+ if (MemberDesc->isProtected()) {
+ Member->AddUInt(DW_AT_accessibility, 0, DW_ACCESS_protected);
+ } else if (MemberDesc->isPrivate()) {
+ Member->AddUInt(DW_AT_accessibility, 0, DW_ACCESS_private);
+ } else if (Tag == DW_TAG_inheritance) {
+ Member->AddUInt(DW_AT_accessibility, 0, DW_ACCESS_public);
+ }
+
+ Ty->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->getDisplayName();
+ const std::string &MangledName = StaticDesc->getName();
+ Static->AddString(DW_AT_name, DW_FORM_string, Name);
+ Static->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+ MangledName);
+
+ // Add location.
+ AddSourceLine(Static, StaticDesc->getFile(), StaticDesc->getLine());
+
+ // Add type.
+ if (TypeDesc *StaticTy = StaticDesc->getType()) {
+ Static->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+ NewType(Context, StaticTy, Unit));
+ }
+
+ // Add flags.
+ Static->AddUInt(DW_AT_external, DW_FORM_flag, 1);
+ Static->AddUInt(DW_AT_declaration, DW_FORM_flag, 1);
+
+ Ty->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->getDisplayName();
+ const std::string &MangledName = MethodDesc->getName();
+ bool IsCTor = false;
+
+ if (Name.empty()) {
+ Method->AddString(DW_AT_name, DW_FORM_string, MangledName);
+ IsCTor = TyDesc->getName() == MangledName;
+ } else {
+ Method->AddString(DW_AT_name, DW_FORM_string, Name);
+ Method->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+ MangledName);
+ }
+
+ // 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.
+ Method->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+ NewType(Context, 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);
+ Arg->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+ NewType(Context, cast<TypeDesc>(Args[i]), Unit));
+ Arg->AddUInt(DW_AT_artificial, DW_FORM_flag, 1);
+ Method->AddChild(Arg);
+ }
+ }
+
+ // Add flags.
+ Method->AddUInt(DW_AT_external, DW_FORM_flag, 1);
+ Method->AddUInt(DW_AT_declaration, DW_FORM_flag, 1);
+
+ Ty->AddChild(Method);
}
-
- // Add computation for offset.
- DIEBlock *Block = new DIEBlock();
- Block->AddUInt(DW_FORM_data1, DW_OP_plus_uconst);
- Block->AddUInt(DW_FORM_udata, FieldOffset >> 3);
- Block->ComputeSize(*this);
- Member->AddBlock(DW_AT_data_member_location, 0, Block);
-
- Ty->AddChild(Member);
}
break;
}
break;
}
+ case DW_TAG_subroutine_type: {
+ // Add prototype flag.
+ Ty->AddUInt(DW_AT_prototyped, DW_FORM_flag, 1);
+ // Add return type.
+ Ty->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+ NewType(Context, 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);
+ Arg->AddDIEntry(DW_AT_type, DW_FORM_ref4,
+ NewType(Context, cast<TypeDesc>(Elements[i]), Unit));
+ Ty->AddChild(Arg);
+ }
+
+ break;
+ }
default: break;
}
}
unsigned ID) {
// Construct debug information entry.
DIE *Die = new DIE(DW_TAG_compile_unit);
- Die->AddLabel (DW_AT_stmt_list, DW_FORM_data4, DWLabel("line", 0));
- Die->AddLabel (DW_AT_high_pc, DW_FORM_addr, DWLabel("text_end", 0));
- Die->AddLabel (DW_AT_low_pc, DW_FORM_addr, DWLabel("text_begin", 0));
+ Die->AddDelta (DW_AT_stmt_list, DW_FORM_data4, DWLabel("line", 0),
+ DWLabel("section_line", 0));
+// Die->AddLabel (DW_AT_high_pc, DW_FORM_addr, DWLabel("text_end", 0));
+// Die->AddLabel (DW_AT_low_pc, DW_FORM_addr, DWLabel("text_begin", 0));
Die->AddString(DW_AT_producer, DW_FORM_string, UnitDesc->getProducer());
Die->AddUInt (DW_AT_language, DW_FORM_data1, UnitDesc->getLanguage());
Die->AddString(DW_AT_name, DW_FORM_string, UnitDesc->getFileName());
// Get the global variable itself.
GlobalVariable *GV = GVD->getGlobalVariable();
- // Generate the mangled name.
- std::string MangledName = Asm->Mang->getValueName(GV);
- // Gather the details (simplify add attribute code.)
- const std::string &Name = GVD->getName();
-
+ const std::string &Name = GVD->hasMangledName() ? GVD->getDisplayName()
+ : GVD->getName();
+ const std::string &MangledName = GVD->hasMangledName() ? GVD->getName()
+ : "";
// Get the global's type.
DIE *Type = NewType(Unit->getDie(), GVD->getType(), Unit);
// Create the globale variable DIE.
DIE *VariableDie = new DIE(DW_TAG_variable);
- VariableDie->AddString (DW_AT_name, DW_FORM_string, Name);
- VariableDie->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
- VariableDie->AddUInt (DW_AT_external, DW_FORM_flag, 1);
+ VariableDie->AddString(DW_AT_name, DW_FORM_string, Name);
+ if (!MangledName.empty()) {
+ VariableDie->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+ MangledName);
+ }
+ VariableDie->AddDIEntry(DW_AT_type, DW_FORM_ref4, Type);
+ VariableDie->AddUInt(DW_AT_external, DW_FORM_flag, 1);
// Add source line info if available.
AddSourceLine(VariableDie, UnitDesc, GVD->getLine());
if (Slot) return Slot;
// Gather the details (simplify add attribute code.)
- const std::string &Name = SPD->getName();
+ const std::string &Name = SPD->hasMangledName() ? SPD->getDisplayName()
+ : SPD->getName();
+ const std::string &MangledName = SPD->hasMangledName() ? SPD->getName()
+ : "";
DIE *Type = NewType(Unit->getDie(), SPD->getType(), Unit);
unsigned IsExternal = SPD->isStatic() ? 0 : 1;
DIE *SubprogramDie = new DIE(DW_TAG_subprogram);
- SubprogramDie->AddString (DW_AT_name, DW_FORM_string, Name);
+ SubprogramDie->AddString(DW_AT_name, DW_FORM_string, Name);
+ if (!MangledName.empty()) {
+ SubprogramDie->AddString(DW_AT_MIPS_linkage_name, DW_FORM_string,
+ MangledName);
+ }
if (Type) {
- SubprogramDie->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
+ SubprogramDie->AddDIEntry(DW_AT_type, DW_FORM_ref4, Type);
}
- SubprogramDie->AddUInt (DW_AT_external, DW_FORM_flag, IsExternal);
- SubprogramDie->AddUInt (DW_AT_prototyped, DW_FORM_flag, 1);
+ SubprogramDie->AddUInt(DW_AT_external, DW_FORM_flag, IsExternal);
+ SubprogramDie->AddUInt(DW_AT_prototyped, DW_FORM_flag, 1);
// Add source line info if available.
AddSourceLine(SubprogramDie, UnitDesc, SPD->getLine());
// Define the Scope debug information entry.
DebugScope *Scope = Scopes[j];
// FIXME - Ignore inlined functions for the time being.
- if (Scope->getParent()) continue;
+ if (!Scope->getParent()) continue;
DIE *ScopeDie = new DIE(DW_TAG_lexical_block);
didInitial = true;
// Dwarf sections base addresses.
- Asm->SwitchToDataSection(DwarfFrameSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfFrameSection(), 0);
EmitLabel("section_frame", 0);
- Asm->SwitchToDataSection(DwarfInfoSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfInfoSection(), 0);
EmitLabel("section_info", 0);
EmitLabel("info", 0);
- Asm->SwitchToDataSection(DwarfAbbrevSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection(), 0);
EmitLabel("section_abbrev", 0);
EmitLabel("abbrev", 0);
- Asm->SwitchToDataSection(DwarfARangesSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfARangesSection(), 0);
EmitLabel("section_aranges", 0);
- Asm->SwitchToDataSection(DwarfMacInfoSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection(), 0);
EmitLabel("section_macinfo", 0);
- Asm->SwitchToDataSection(DwarfLineSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfLineSection(), 0);
EmitLabel("section_line", 0);
EmitLabel("line", 0);
- Asm->SwitchToDataSection(DwarfLocSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfLocSection(), 0);
EmitLabel("section_loc", 0);
- Asm->SwitchToDataSection(DwarfPubNamesSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection(), 0);
EmitLabel("section_pubnames", 0);
- Asm->SwitchToDataSection(DwarfStrSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfStrSection(), 0);
EmitLabel("section_str", 0);
- Asm->SwitchToDataSection(DwarfRangesSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfRangesSection(), 0);
EmitLabel("section_ranges", 0);
- Asm->SwitchToDataSection(TextSection, 0);
+ Asm->SwitchToTextSection(TAI->getTextSection(), 0);
EmitLabel("text_begin", 0);
- Asm->SwitchToDataSection(DataSection, 0);
+ Asm->SwitchToDataSection(TAI->getDataSection(), 0);
EmitLabel("data_begin", 0);
-
+
// Emit common frame information.
EmitInitialDebugFrame();
}
// Advance row if new location.
if (BaseLabel && LabelID && BaseLabelID != LabelID) {
- EmitULEB128Bytes(DW_CFA_advance_loc4);
+ EmitInt8(DW_CFA_advance_loc4);
EOL("DW_CFA_advance_loc4");
EmitDifference("loc", LabelID, BaseLabel, BaseLabelID);
EOL("");
BaseLabel = "loc";
}
+ int stackGrowth =
+ Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
+ TargetFrameInfo::StackGrowsUp ?
+ TAI->getAddressSize() : -TAI->getAddressSize();
+
// If advancing cfa.
if (Dst.isRegister() && Dst.getRegister() == MachineLocation::VirtualFP) {
if (!Src.isRegister()) {
if (Src.getRegister() == MachineLocation::VirtualFP) {
- EmitULEB128Bytes(DW_CFA_def_cfa_offset);
+ EmitInt8(DW_CFA_def_cfa_offset);
EOL("DW_CFA_def_cfa_offset");
} else {
- EmitULEB128Bytes(DW_CFA_def_cfa);
+ EmitInt8(DW_CFA_def_cfa);
EOL("DW_CFA_def_cfa");
EmitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister()));
EOL("Register");
}
- int stackGrowth =
- Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
- TargetFrameInfo::StackGrowsUp ?
- AddressSize : -AddressSize;
+ int Offset = Src.getOffset() / stackGrowth;
- EmitULEB128Bytes(Src.getOffset() / stackGrowth);
+ EmitULEB128Bytes(Offset);
EOL("Offset");
} else {
+ assert(0 && "Machine move no supported yet.");
}
} else {
+ unsigned Reg = RI->getDwarfRegNum(Src.getRegister());
+ int Offset = Dst.getOffset() / stackGrowth;
+
+ if (Offset < 0) {
+ EmitInt8(DW_CFA_offset_extended_sf);
+ EOL("DW_CFA_offset_extended_sf");
+ EmitULEB128Bytes(Reg);
+ EOL("Reg");
+ EmitSLEB128Bytes(Offset);
+ EOL("Offset");
+ } else if (Reg < 64) {
+ EmitInt8(DW_CFA_offset + Reg);
+ EOL("DW_CFA_offset + Reg");
+ EmitULEB128Bytes(Offset);
+ EOL("Offset");
+ } else {
+ EmitInt8(DW_CFA_offset_extended);
+ EOL("DW_CFA_offset_extended");
+ EmitULEB128Bytes(Reg);
+ EOL("Reg");
+ EmitULEB128Bytes(Offset);
+ EOL("Offset");
+ }
}
}
}
///
void DwarfWriter::EmitDebugInfo() const {
// Start debug info section.
- Asm->SwitchToDataSection(DwarfInfoSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfInfoSection(), 0);
// Process each compile unit.
for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
EmitInt32(ContentSize); EOL("Length of Compilation Unit Info");
EmitInt16(DWARF_VERSION); EOL("DWARF version number");
- EmitReference("abbrev_begin", 0); EOL("Offset Into Abbrev. Section");
- EmitInt8(AddressSize); EOL("Address Size (in bytes)");
+ EmitDifference("abbrev_begin", 0, "section_abbrev", 0);
+ EOL("Offset Into Abbrev. Section");
+ EmitInt8(TAI->getAddressSize()); EOL("Address Size (in bytes)");
EmitDIE(Die);
EmitLabel("info_end", Unit->getID());
// Check to see if it is worth the effort.
if (!Abbreviations.empty()) {
// Start the debug abbrev section.
- Asm->SwitchToDataSection(DwarfAbbrevSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfAbbrevSection(), 0);
EmitLabel("abbrev_begin", 0);
const int MaxLineDelta = 255 + MinLineDelta;
// Start the dwarf line section.
- Asm->SwitchToDataSection(DwarfLineSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfLineSection(), 0);
// Construct the section header.
EmitLabel("line_prolog_end", 0);
- // Emit line information
- const std::vector<SourceLineInfo *> &LineInfos = DebugInfo->getSourceLines();
-
- // Dwarf assumes we start with first line of first source file.
- unsigned Source = 1;
- unsigned Line = 1;
-
- // Construct rows of the address, source, line, column matrix.
- for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
- SourceLineInfo *LineInfo = LineInfos[i];
+ // A sequence for each text section.
+ for (unsigned j = 0, M = SectionSourceLines.size(); j < M; ++j) {
+ // Isolate current sections line info.
+ const std::vector<SourceLineInfo *> &LineInfos = SectionSourceLines[j];
if (DwarfVerbose) {
- unsigned SourceID = LineInfo->getSourceID();
- const SourceFileInfo &SourceFile = SourceFiles[SourceID];
- unsigned DirectoryID = SourceFile.getDirectoryID();
O << "\t"
- << Asm->CommentString << " "
- << Directories[DirectoryID]
- << SourceFile.getName() << ":"
- << LineInfo->getLine() << "\n";
+ << TAI->getCommentString() << " "
+ << "Section "
+ << SectionMap[j + 1].c_str() << "\n";
}
- // Define the line address.
- EmitInt8(0); EOL("Extended Op");
- EmitInt8(4 + 1); EOL("Op size");
- EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
- EmitReference("loc", LineInfo->getLabelID()); EOL("Location label");
-
- // If change of source, then switch to the new source.
- if (Source != LineInfo->getSourceID()) {
- Source = LineInfo->getSourceID();
- EmitInt8(DW_LNS_set_file); EOL("DW_LNS_set_file");
- EmitULEB128Bytes(Source); EOL("New Source");
- }
+ // Dwarf assumes we start with first line of first source file.
+ unsigned Source = 1;
+ unsigned Line = 1;
- // If change of line.
- if (Line != LineInfo->getLine()) {
- // Determine offset.
- int Offset = LineInfo->getLine() - Line;
- int Delta = Offset - MinLineDelta;
+ // Construct rows of the address, source, line, column matrix.
+ for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
+ SourceLineInfo *LineInfo = LineInfos[i];
- // Update line.
- Line = LineInfo->getLine();
+ if (DwarfVerbose) {
+ unsigned SourceID = LineInfo->getSourceID();
+ const SourceFileInfo &SourceFile = SourceFiles[SourceID];
+ unsigned DirectoryID = SourceFile.getDirectoryID();
+ O << "\t"
+ << TAI->getCommentString() << " "
+ << Directories[DirectoryID]
+ << SourceFile.getName() << ":"
+ << LineInfo->getLine() << "\n";
+ }
+
+ // Define the line address.
+ EmitInt8(0); EOL("Extended Op");
+ EmitInt8(4 + 1); EOL("Op size");
+ EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
+ EmitReference("loc", LineInfo->getLabelID()); EOL("Location label");
- // If delta is small enough and in range...
- if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
- // ... then use fast opcode.
- EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
+ // If change of source, then switch to the new source.
+ if (Source != LineInfo->getSourceID()) {
+ Source = LineInfo->getSourceID();
+ EmitInt8(DW_LNS_set_file); EOL("DW_LNS_set_file");
+ EmitULEB128Bytes(Source); EOL("New Source");
+ }
+
+ // If change of line.
+ if (Line != LineInfo->getLine()) {
+ // Determine offset.
+ int Offset = LineInfo->getLine() - Line;
+ int Delta = Offset - MinLineDelta;
+
+ // Update line.
+ Line = LineInfo->getLine();
+
+ // If delta is small enough and in range...
+ if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
+ // ... then use fast opcode.
+ EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
+ } else {
+ // ... otherwise use long hand.
+ EmitInt8(DW_LNS_advance_line); EOL("DW_LNS_advance_line");
+ EmitSLEB128Bytes(Offset); EOL("Line Offset");
+ EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
+ }
} else {
- // ... otherwise use long hand.
- EmitInt8(DW_LNS_advance_line); EOL("DW_LNS_advance_line");
- EmitSLEB128Bytes(Offset); EOL("Line Offset");
+ // Copy the previous row (different address or source)
EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
}
- } else {
- // Copy the previous row (different address or source)
- EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
}
- }
- // Define last address.
- EmitInt8(0); EOL("Extended Op");
- EmitInt8(4 + 1); EOL("Op size");
- EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
- EmitReference("text_end", 0); EOL("Location label");
+ // Define last address of section.
+ EmitInt8(0); EOL("Extended Op");
+ EmitInt8(4 + 1); EOL("Op size");
+ EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
+ EmitReference("section_end", j + 1); EOL("Section end label");
- // Mark end of matrix.
- EmitInt8(0); EOL("DW_LNE_end_sequence");
- EmitULEB128Bytes(1); O << "\n";
- EmitInt8(1); O << "\n";
+ // Mark end of matrix.
+ EmitInt8(0); EOL("DW_LNE_end_sequence");
+ EmitULEB128Bytes(1); O << "\n";
+ EmitInt8(1); O << "\n";
+ }
EmitLabel("line_end", 0);
int stackGrowth =
Asm->TM.getFrameInfo()->getStackGrowthDirection() ==
TargetFrameInfo::StackGrowsUp ?
- AddressSize : -AddressSize;
+ TAI->getAddressSize() : -TAI->getAddressSize();
// Start the dwarf frame section.
- Asm->SwitchToDataSection(DwarfFrameSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfFrameSection(), 0);
+ EmitLabel("frame_common", 0);
EmitDifference("frame_common_end", 0,
"frame_common_begin", 0);
EOL("Length of Common Information Entry");
/// section.
void DwarfWriter::EmitFunctionDebugFrame() {
// Start the dwarf frame section.
- Asm->SwitchToDataSection(DwarfFrameSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfFrameSection(), 0);
EmitDifference("frame_end", SubprogramCount,
"frame_begin", SubprogramCount);
EmitLabel("frame_begin", SubprogramCount);
- EmitReference("section_frame", 0); EOL("FDE CIE offset");
+ EmitDifference("frame_common", 0, "section_frame", 0);
+ EOL("FDE CIE offset");
EmitReference("func_begin", SubprogramCount); EOL("FDE initial location");
EmitDifference("func_end", SubprogramCount,
///
void DwarfWriter::EmitDebugPubNames() {
// Start the dwarf pubnames section.
- Asm->SwitchToDataSection(DwarfPubNamesSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfPubNamesSection(), 0);
// Process each compile unit.
for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
EmitInt16(DWARF_VERSION); EOL("DWARF Version");
- EmitReference("info_begin", Unit->getID());
+ EmitDifference("info_begin", Unit->getID(), "section_info", 0);
EOL("Offset of Compilation Unit Info");
EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID());
// Check to see if it is worth the effort.
if (!StringPool.empty()) {
// Start the dwarf str section.
- Asm->SwitchToDataSection(DwarfStrSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfStrSection(), 0);
// For each of strings in the string pool.
for (unsigned StringID = 1, N = StringPool.size();
///
void DwarfWriter::EmitDebugLoc() {
// Start the dwarf loc section.
- Asm->SwitchToDataSection(DwarfLocSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfLocSection(), 0);
O << "\n";
}
///
void DwarfWriter::EmitDebugARanges() {
// Start the dwarf aranges section.
- Asm->SwitchToDataSection(DwarfARangesSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfARangesSection(), 0);
// FIXME - Mock up
#if 0
EmitReference("info_begin", Unit->getID());
EOL("Offset of Compilation Unit Info");
- EmitInt8(AddressSize); EOL("Size of Address");
+ EmitInt8(TAI->getAddressSize()); EOL("Size of Address");
EmitInt8(0); EOL("Size of Segment Descriptor");
///
void DwarfWriter::EmitDebugRanges() {
// Start the dwarf ranges section.
- Asm->SwitchToDataSection(DwarfRangesSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfRangesSection(), 0);
O << "\n";
}
///
void DwarfWriter::EmitDebugMacInfo() {
// Start the dwarf macinfo section.
- Asm->SwitchToDataSection(DwarfMacInfoSection, 0);
+ Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection(), 0);
O << "\n";
}
// Main entry points.
//
-DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A)
+DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A,
+ const TargetAsmInfo *T)
: O(OS)
, Asm(A)
+, TAI(T)
, TD(Asm->TM.getTargetData())
, RI(Asm->TM.getRegisterInfo())
, M(NULL)
, DebugInfo(NULL)
, didInitial(false)
, shouldEmit(false)
-, IsNormalText(false)
, SubprogramCount(0)
, CompileUnits()
, Abbreviations()
, StringPool()
, DescToUnitMap()
, DescToDieMap()
-, TypeToDieMap()
-, AddressSize(sizeof(int32_t))
-, hasLEB128(false)
-, hasDotLoc(false)
-, hasDotFile(false)
-, needsSet(false)
-, DwarfAbbrevSection(".debug_abbrev")
-, DwarfInfoSection(".debug_info")
-, DwarfLineSection(".debug_line")
-, DwarfFrameSection(".debug_frame")
-, DwarfPubNamesSection(".debug_pubnames")
-, DwarfPubTypesSection(".debug_pubtypes")
-, DwarfStrSection(".debug_str")
-, DwarfLocSection(".debug_loc")
-, DwarfARangesSection(".debug_aranges")
-, DwarfRangesSection(".debug_ranges")
-, DwarfMacInfoSection(".debug_macinfo")
-, TextSection(".text")
-, DataSection(".data")
+, SectionMap()
+, SectionSourceLines()
{}
DwarfWriter::~DwarfWriter() {
for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
// Create DIEs for each of the externally visible subprograms.
ConstructSubprogramDIEs();
+
+ // Prime section data.
+ SectionMap.insert(std::string("\t") + TAI->getTextSection());
}
}
EOL("Dwarf End Module");
// Standard sections final addresses.
- Asm->SwitchToTextSection(TextSection, 0);
+ Asm->SwitchToTextSection(TAI->getTextSection(), 0);
EmitLabel("text_end", 0);
- Asm->SwitchToDataSection(DataSection, 0);
+ Asm->SwitchToDataSection(TAI->getDataSection(), 0);
EmitLabel("data_end", 0);
+ // End text sections.
+ for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) {
+ Asm->SwitchToTextSection(SectionMap[i].c_str(), 0);
+ EmitLabel("section_end", i);
+ }
+
// Compute DIE offsets and sizes.
SizeAndOffsets();
/// BeginFunction - Gather pre-function debug information. Assumes being
/// emitted immediately after the function entry point.
-void DwarfWriter::BeginFunction(MachineFunction *MF, bool IsNormalText) {
+void DwarfWriter::BeginFunction(MachineFunction *MF) {
this->MF = MF;
- // FIXME - should be able to debug coalesced functions.
- this->IsNormalText = IsNormalText;
- // FIXME - should be able to debug coalesced functions.
- if (IsNormalText) {
- // Begin accumulating function debug information.
- DebugInfo->BeginFunction(MF);
-
- if (!ShouldEmitDwarf()) return;
- EOL("Dwarf Begin Function");
+ if (!ShouldEmitDwarf()) return;
+ EOL("Dwarf Begin Function");
+
+ // Begin accumulating function debug information.
+ DebugInfo->BeginFunction(MF);
- // Assumes in correct section after the entry point.
- EmitLabel("func_begin", ++SubprogramCount);
- } else {
- ShouldEmitDwarf();
- }
+ // Assumes in correct section after the entry point.
+ EmitLabel("func_begin", ++SubprogramCount);
}
/// EndFunction - Gather and emit post-function debug information.
if (!ShouldEmitDwarf()) return;
EOL("Dwarf End Function");
- // FIXME - should be able to debug coalesced functions.
- if (IsNormalText) {
- // Define end label for subprogram.
- EmitLabel("func_end", SubprogramCount);
-
- // Construct scopes for subprogram.
- ConstructRootScope(DebugInfo->getRootScope());
+ // Define end label for subprogram.
+ EmitLabel("func_end", SubprogramCount);
- // Emit function frame information.
- EmitFunctionDebugFrame();
+ // Get function line info.
+ std::vector<SourceLineInfo *> &LineInfos = DebugInfo->getSourceLines();
+
+ if (!LineInfos.empty()) {
+ // Get section line info.
+ unsigned ID = SectionMap.insert(Asm->CurrentSection);
+ if (SectionSourceLines.size() < ID) SectionSourceLines.resize(ID);
+ std::vector<SourceLineInfo *> &SectionLineInfos =SectionSourceLines[ID-1];
+ // Append the function info to section info.
+ SectionLineInfos.insert(SectionLineInfos.end(),
+ LineInfos.begin(), LineInfos.end());
}
+ // Construct scopes for subprogram.
+ ConstructRootScope(DebugInfo->getRootScope());
+
+ // Emit function frame information.
+ EmitFunctionDebugFrame();
+
+ // Reset the line numbers for the next function.
+ LineInfos.clear();
+
// Clear function debug information.
DebugInfo->EndFunction();
}