+ Asm->getObjFileLowering().getDwarfARangesSection());
+
+ typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType;
+
+ SpansType Spans;
+
+ // Build a list of sections used.
+ std::vector<const MCSection *> Sections;
+ for (const auto &it : SectionMap) {
+ const MCSection *Section = it.first;
+ Sections.push_back(Section);
+ }
+
+ // Sort the sections into order.
+ // This is only done to ensure consistent output order across different runs.
+ std::sort(Sections.begin(), Sections.end(), SectionSort);
+
+ // Build a set of address spans, sorted by CU.
+ for (const MCSection *Section : Sections) {
+ SmallVector<SymbolCU, 8> &List = SectionMap[Section];
+ if (List.size() < 2)
+ continue;
+
+ // Sort the symbols by offset within the section.
+ std::sort(List.begin(), List.end(),
+ [&](const SymbolCU &A, const SymbolCU &B) {
+ unsigned IA = A.Sym ? Asm->OutStreamer.GetSymbolOrder(A.Sym) : 0;
+ unsigned IB = B.Sym ? Asm->OutStreamer.GetSymbolOrder(B.Sym) : 0;
+
+ // Symbols with no order assigned should be placed at the end.
+ // (e.g. section end labels)
+ if (IA == 0)
+ return false;
+ if (IB == 0)
+ return true;
+ return IA < IB;
+ });
+
+ // If we have no section (e.g. common), just write out
+ // individual spans for each symbol.
+ if (Section == NULL) {
+ for (const SymbolCU &Cur : List) {
+ ArangeSpan Span;
+ Span.Start = Cur.Sym;
+ Span.End = NULL;
+ if (Cur.CU)
+ Spans[Cur.CU].push_back(Span);
+ }
+ } else {
+ // Build spans between each label.
+ const MCSymbol *StartSym = List[0].Sym;
+ for (size_t n = 1, e = List.size(); n < e; n++) {
+ const SymbolCU &Prev = List[n - 1];
+ const SymbolCU &Cur = List[n];
+
+ // Try and build the longest span we can within the same CU.
+ if (Cur.CU != Prev.CU) {
+ ArangeSpan Span;
+ Span.Start = StartSym;
+ Span.End = Cur.Sym;
+ Spans[Prev.CU].push_back(Span);
+ StartSym = Cur.Sym;
+ }
+ }
+ }
+ }
+
+ unsigned PtrSize = Asm->getDataLayout().getPointerSize();
+
+ // Build a list of CUs used.
+ std::vector<DwarfCompileUnit *> CUs;
+ for (const auto &it : Spans) {
+ DwarfCompileUnit *CU = it.first;
+ CUs.push_back(CU);
+ }
+
+ // Sort the CU list (again, to ensure consistent output order).
+ std::sort(CUs.begin(), CUs.end(), [](const DwarfUnit *A, const DwarfUnit *B) {
+ return A->getUniqueID() < B->getUniqueID();
+ });
+
+ // Emit an arange table for each CU we used.
+ for (DwarfCompileUnit *CU : CUs) {
+ std::vector<ArangeSpan> &List = Spans[CU];
+
+ // Emit size of content not including length itself.
+ unsigned ContentSize =
+ sizeof(int16_t) + // DWARF ARange version number
+ sizeof(int32_t) + // Offset of CU in the .debug_info section
+ sizeof(int8_t) + // Pointer Size (in bytes)
+ sizeof(int8_t); // Segment Size (in bytes)
+
+ unsigned TupleSize = PtrSize * 2;
+
+ // 7.20 in the Dwarf specs requires the table to be aligned to a tuple.
+ unsigned Padding =
+ OffsetToAlignment(sizeof(int32_t) + ContentSize, TupleSize);
+
+ ContentSize += Padding;
+ ContentSize += (List.size() + 1) * TupleSize;
+
+ // For each compile unit, write the list of spans it covers.
+ Asm->OutStreamer.AddComment("Length of ARange Set");
+ Asm->EmitInt32(ContentSize);
+ Asm->OutStreamer.AddComment("DWARF Arange version number");
+ Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
+ Asm->OutStreamer.AddComment("Offset Into Debug Info Section");
+ Asm->EmitSectionOffset(CU->getLocalLabelBegin(), CU->getLocalSectionSym());
+ Asm->OutStreamer.AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(PtrSize);
+ Asm->OutStreamer.AddComment("Segment Size (in bytes)");
+ Asm->EmitInt8(0);
+
+ Asm->OutStreamer.EmitFill(Padding, 0xff);
+
+ for (const ArangeSpan &Span : List) {
+ Asm->EmitLabelReference(Span.Start, PtrSize);
+
+ // Calculate the size as being from the span start to it's end.
+ if (Span.End) {
+ Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize);
+ } else {
+ // For symbols without an end marker (e.g. common), we
+ // write a single arange entry containing just that one symbol.
+ uint64_t Size = SymSize[Span.Start];
+ if (Size == 0)
+ Size = 1;
+
+ Asm->OutStreamer.EmitIntValue(Size, PtrSize);
+ }
+ }
+
+ Asm->OutStreamer.AddComment("ARange terminator");
+ Asm->OutStreamer.EmitIntValue(0, PtrSize);
+ Asm->OutStreamer.EmitIntValue(0, PtrSize);
+ }