#include "DwarfAccelTable.h"
#include "DwarfDebug.h"
#include "llvm/ADT/APFloat.h"
-#include "llvm/DIBuilder.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
}
}
+unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) {
+ // If we print assembly, we can't separate .file entries according to
+ // compile units. Thus all files will belong to the default compile unit.
+
+ // FIXME: add a better feature test than hasRawTextSupport. Even better,
+ // extend .file to support this.
+ return Asm->OutStreamer.EmitDwarfFileDirective(
+ 0, DirName, FileName,
+ Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID());
+}
+
/// addOpAddress - Add a dwarf op address data and value using the
/// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index.
///
Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
}
+void DwarfUnit::addLabelDelta(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
+ DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
+ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
+}
+
/// addDIEEntry - Add a DIE attribute data and value.
///
void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) {
if (Line == 0)
return;
- unsigned FileID =
- DD->getOrCreateSourceID(File, Directory, getCU().getUniqueID());
+ unsigned FileID = getCU().getOrCreateSourceID(File, Directory);
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
DIType BaseType = DD->resolve(Ty.getTypeDerivedFrom());
- // If this type is not derived from any type then take conservative approach.
- if (!BaseType.isValid())
+ // If this type is not derived from any type or the type is a declaration then
+ // take conservative approach.
+ if (!BaseType.isValid() || BaseType.isForwardDecl())
return Ty.getSizeInBits();
// If this is a derived type, go ahead and get the base type, unless it's a
DIE *ContextDIE = getOrCreateContextDIE(Context);
assert(ContextDIE);
+ // Unique the type. This is a noop if the type has no unique identifier.
+ Ty = DIType(resolve(Ty.getRef()));
+
DIE *TyDIE = getDIE(Ty);
if (TyDIE)
return TyDIE;
// Create new type.
TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);
+ updateAcceleratorTables(Context, Ty, TyDIE);
+
if (Ty.isBasicType())
constructTypeDIE(*TyDIE, DIBasicType(Ty));
else if (Ty.isCompositeType()) {
if (GenerateDwarfTypeUnits && !Ty.isForwardDecl())
if (MDString *TypeId = CTy.getIdentifier()) {
DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
- // Skip updating the accellerator tables since this is not the full type
+ // Skip updating the accelerator tables since this is not the full type.
return TyDIE;
}
constructTypeDIE(*TyDIE, CTy);
constructTypeDIE(*TyDIE, DIDerivedType(Ty));
}
- updateAcceleratorTables(Context, Ty, TyDIE);
-
return TyDIE;
}
unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0;
addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags));
- if (!Context || Context.isCompileUnit() || Context.isFile() ||
- Context.isNameSpace())
+ if ((!Context || Context.isCompileUnit() || Context.isFile() ||
+ Context.isNameSpace()) &&
+ getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly)
GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = TyDIE;
}
}
/// addGlobalName - Add a new global name to the compile unit.
void DwarfUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) {
+ if (getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly)
+ return;
std::string FullName = getParentContextString(Context) + Name.str();
GlobalNames[FullName] = Die;
}
return NDie;
}
+/// Unique C++ member function declarations based on their
+/// context and mangled name.
+DISubprogram
+DwarfUnit::getOdrUniqueSubprogram(DIScope Context, DISubprogram SP) const {
+ if (!hasODR() ||
+ !Context.isCompositeType() ||
+ SP.getLinkageName().empty() ||
+ SP.isDefinition())
+ return SP;
+ // Create a key with the UID of the parent class and this SP's name.
+ Twine Key = SP.getContext().getName() + SP.getLinkageName();
+ const MDNode *&Entry = DD->getOrCreateOdrMember(Key.str());
+ if (!Entry)
+ Entry = &*SP;
+
+ return DISubprogram(Entry);
+}
+
/// getOrCreateSubprogramDIE - Create new DIE using SP.
DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE (as is the case for member function
// declarations).
- DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext()));
+ DIScope Context = resolve(SP.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
+ // Unique declarations based on the ODR, where applicable.
+ SP = getOdrUniqueSubprogram(Context, SP);
DIE *SPDie = getDIE(SP);
if (SPDie)
// TAG_variable.
addString(IsStaticMember && VariableSpecDIE ? VariableSpecDIE
: VariableDIE,
- dwarf::DW_AT_MIPS_linkage_name,
+ DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name
+ : dwarf::DW_AT_MIPS_linkage_name,
GlobalValue::getRealLinkageName(LinkageName));
} else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV.getConstant())) {
uint64_t OffsetInBytes;
if (Size != FieldSize) {
- // Handle bitfield.
- addUInt(MemberDie, dwarf::DW_AT_byte_size, None,
- getBaseTypeSize(DD, DT) >> 3);
- addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits());
+ // Handle bitfield, assume bytes are 8 bits.
+ addUInt(MemberDie, dwarf::DW_AT_byte_size, None, FieldSize/8);
+ addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size);
uint64_t Offset = DT.getOffsetInBits();
uint64_t AlignMask = ~(DT.getAlignInBits() - 1);