[AMDGPU] Test codegen'ing True16 additions.
[llvm-project.git] / llvm / lib / DWARFLinkerParallel / DIEAttributeCloner.cpp
blob25a55026dd67552f36e597e96655bc8dea95bc60
1 //=== DIEAttributeCloner.cpp ----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "DIEAttributeCloner.h"
10 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
12 namespace llvm {
13 namespace dwarflinker_parallel {
15 void DIEAttributeCloner::clone() {
16 DWARFUnit &U = CU.getOrigUnit();
18 // Extract and clone every attribute.
19 DWARFDataExtractor Data = U.getDebugInfoExtractor();
21 uint64_t Offset = InputDieEntry->getOffset();
22 // Point to the next DIE (generally there is always at least a NULL
23 // entry after the current one). If this is a lone
24 // DW_TAG_compile_unit without any children, point to the next unit.
25 uint64_t NextOffset = (InputDIEIdx + 1 < U.getNumDIEs())
26 ? U.getDIEAtIndex(InputDIEIdx + 1).getOffset()
27 : U.getNextUnitOffset();
29 // We could copy the data only if we need to apply a relocation to it. After
30 // testing, it seems there is no performance downside to doing the copy
31 // unconditionally, and it makes the code simpler.
32 SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
33 Data =
34 DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
36 // Modify the copy with relocated addresses.
37 CU.getContaingFile().Addresses->applyValidRelocs(DIECopy, Offset,
38 Data.isLittleEndian());
40 // Reset the Offset to 0 as we will be working on the local copy of
41 // the data.
42 Offset = 0;
44 const auto *Abbrev = InputDieEntry->getAbbreviationDeclarationPtr();
45 Offset += getULEB128Size(Abbrev->getCode());
47 // Set current output offset.
48 AttrOutOffset = OutDIE->getOffset();
49 for (const auto &AttrSpec : Abbrev->attributes()) {
50 // Check whether current attribute should be skipped.
51 if (shouldSkipAttribute(AttrSpec)) {
52 DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
53 U.getFormParams());
54 continue;
57 DWARFFormValue Val = AttrSpec.getFormValue();
58 Val.extractValue(Data, &Offset, U.getFormParams(), &U);
60 // Clone current attribute.
61 switch (AttrSpec.Form) {
62 case dwarf::DW_FORM_strp:
63 case dwarf::DW_FORM_line_strp:
64 case dwarf::DW_FORM_string:
65 case dwarf::DW_FORM_strx:
66 case dwarf::DW_FORM_strx1:
67 case dwarf::DW_FORM_strx2:
68 case dwarf::DW_FORM_strx3:
69 case dwarf::DW_FORM_strx4:
70 AttrOutOffset += cloneStringAttr(Val, AttrSpec);
71 break;
72 case dwarf::DW_FORM_ref_addr:
73 case dwarf::DW_FORM_ref1:
74 case dwarf::DW_FORM_ref2:
75 case dwarf::DW_FORM_ref4:
76 case dwarf::DW_FORM_ref8:
77 case dwarf::DW_FORM_ref_udata:
78 AttrOutOffset += cloneDieRefAttr(Val, AttrSpec);
79 break;
80 case dwarf::DW_FORM_data1:
81 case dwarf::DW_FORM_data2:
82 case dwarf::DW_FORM_data4:
83 case dwarf::DW_FORM_data8:
84 case dwarf::DW_FORM_udata:
85 case dwarf::DW_FORM_sdata:
86 case dwarf::DW_FORM_sec_offset:
87 case dwarf::DW_FORM_flag:
88 case dwarf::DW_FORM_flag_present:
89 case dwarf::DW_FORM_rnglistx:
90 case dwarf::DW_FORM_loclistx:
91 case dwarf::DW_FORM_implicit_const:
92 AttrOutOffset += cloneScalarAttr(Val, AttrSpec);
93 break;
94 case dwarf::DW_FORM_block:
95 case dwarf::DW_FORM_block1:
96 case dwarf::DW_FORM_block2:
97 case dwarf::DW_FORM_block4:
98 case dwarf::DW_FORM_exprloc:
99 AttrOutOffset += cloneBlockAttr(Val, AttrSpec);
100 break;
101 case dwarf::DW_FORM_addr:
102 case dwarf::DW_FORM_addrx:
103 case dwarf::DW_FORM_addrx1:
104 case dwarf::DW_FORM_addrx2:
105 case dwarf::DW_FORM_addrx3:
106 case dwarf::DW_FORM_addrx4:
107 AttrOutOffset += cloneAddressAttr(Val, AttrSpec);
108 break;
109 default:
110 CU.warn("unsupported attribute form " +
111 dwarf::FormEncodingString(AttrSpec.Form) +
112 " in DieAttributeCloner::clone(). Dropping.",
113 InputDieEntry);
117 // We convert source strings into the indexed form for DWARFv5.
118 // Check if original compile unit already has DW_AT_str_offsets_base
119 // attribute.
120 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
121 CU.getVersion() >= 5 && !AttrInfo.HasStringOffsetBaseAttr) {
122 DebugInfoOutputSection.notePatchWithOffsetUpdate(
123 DebugOffsetPatch{
124 AttrOutOffset,
125 &CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets),
126 true},
127 PatchesOffsets);
129 AttrOutOffset += Generator
130 .addScalarAttribute(dwarf::DW_AT_str_offsets_base,
131 dwarf::DW_FORM_sec_offset,
132 CU.getDebugStrOffsetsHeaderSize())
133 .second;
137 bool DIEAttributeCloner::shouldSkipAttribute(
138 DWARFAbbreviationDeclaration::AttributeSpec AttrSpec) {
139 switch (AttrSpec.Attr) {
140 default:
141 return false;
142 case dwarf::DW_AT_low_pc:
143 case dwarf::DW_AT_high_pc:
144 case dwarf::DW_AT_ranges:
145 if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
146 return false;
148 // Skip address attribute if we are in function scope and function does not
149 // reference live address.
150 return CU.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
151 !FuncAddressAdjustment.has_value();
152 case dwarf::DW_AT_rnglists_base:
153 // In case !Update the .debug_addr table is not generated/preserved.
154 // Thus instead of DW_FORM_rnglistx the DW_FORM_sec_offset is used.
155 // Since DW_AT_rnglists_base is used for only DW_FORM_rnglistx the
156 // DW_AT_rnglists_base is removed.
157 return !CU.getGlobalData().getOptions().UpdateIndexTablesOnly;
158 case dwarf::DW_AT_loclists_base:
159 // In case !Update the .debug_addr table is not generated/preserved.
160 // Thus instead of DW_FORM_loclistx the DW_FORM_sec_offset is used.
161 // Since DW_AT_loclists_base is used for only DW_FORM_loclistx the
162 // DW_AT_loclists_base is removed.
163 return !CU.getGlobalData().getOptions().UpdateIndexTablesOnly;
164 case dwarf::DW_AT_location:
165 case dwarf::DW_AT_frame_base:
166 if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
167 return false;
169 // When location expression contains an address: skip this attribute
170 // if it does not reference live address.
171 if (HasLocationExpressionAddress)
172 return !VarAddressAdjustment.has_value();
174 // Skip location attribute if we are in function scope and function does not
175 // reference live address.
176 return CU.getDIEInfo(InputDIEIdx).getIsInFunctionScope() &&
177 !FuncAddressAdjustment.has_value();
181 size_t DIEAttributeCloner::cloneStringAttr(
182 const DWARFFormValue &Val,
183 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
184 std::optional<const char *> String = dwarf::toString(Val);
185 if (!String) {
186 CU.warn("cann't read string attribute.");
187 return 0;
190 StringEntry *StringInPool =
191 CU.getGlobalData().getStringPool().insert(*String).first;
192 if (AttrSpec.Form == dwarf::DW_FORM_line_strp) {
193 DebugInfoOutputSection.notePatchWithOffsetUpdate(
194 DebugLineStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
195 return Generator
196 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_line_strp)
197 .second;
200 // Update attributes info.
201 if (AttrSpec.Attr == dwarf::DW_AT_name)
202 AttrInfo.Name = StringInPool;
203 else if (AttrSpec.Attr == dwarf::DW_AT_MIPS_linkage_name ||
204 AttrSpec.Attr == dwarf::DW_AT_linkage_name)
205 AttrInfo.MangledName = StringInPool;
207 if (CU.getVersion() < 5) {
208 DebugInfoOutputSection.notePatchWithOffsetUpdate(
209 DebugStrPatch{{AttrOutOffset}, StringInPool}, PatchesOffsets);
211 return Generator
212 .addStringPlaceholderAttribute(AttrSpec.Attr, dwarf::DW_FORM_strp)
213 .second;
216 return Generator
217 .addIndexedStringAttribute(AttrSpec.Attr, dwarf::DW_FORM_strx,
218 CU.getDebugStrIndex(StringInPool))
219 .second;
222 size_t DIEAttributeCloner::cloneDieRefAttr(
223 const DWARFFormValue &Val,
224 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
225 if (AttrSpec.Attr == dwarf::DW_AT_sibling)
226 return 0;
228 std::optional<std::pair<CompileUnit *, uint32_t>> RefDiePair =
229 CU.resolveDIEReference(Val);
230 if (!RefDiePair) {
231 // If the referenced DIE is not found, drop the attribute.
232 CU.warn("cann't find referenced DIE.", InputDieEntry);
233 return 0;
235 assert(RefDiePair->first->getStage() >= CompileUnit::Stage::Loaded);
236 assert(RefDiePair->second != 0);
238 // Get output offset for referenced DIE.
239 uint64_t OutDieOffset =
240 RefDiePair->first->getDieOutOffset(RefDiePair->second);
242 // Examine whether referenced DIE is in current compile unit.
243 bool IsLocal = CU.getUniqueID() == RefDiePair->first->getUniqueID();
245 // Set attribute form basing on the kind of referenced DIE(local or not?).
246 dwarf::Form NewForm = IsLocal ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr;
248 // Check whether current attribute references already cloned DIE inside
249 // the same compilation unit. If true - write the already known offset value.
250 if (IsLocal && (OutDieOffset != 0))
251 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, OutDieOffset)
252 .second;
254 // If offset value is not known at this point then create patch for the
255 // reference value and write dummy value into the attribute.
256 DebugInfoOutputSection.notePatchWithOffsetUpdate(
257 DebugDieRefPatch{AttrOutOffset, &CU, RefDiePair->first,
258 RefDiePair->second},
259 PatchesOffsets);
260 return Generator.addScalarAttribute(AttrSpec.Attr, NewForm, 0xBADDEF).second;
263 size_t DIEAttributeCloner::cloneScalarAttr(
264 const DWARFFormValue &Val,
265 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
267 // Create patches for attribute referencing other non invariant section.
268 // Invariant section could not be updated here as this section and
269 // reference to it do not change value in case --update.
270 if (AttrSpec.Attr == dwarf::DW_AT_macro_info) {
271 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
272 const DWARFDebugMacro *Macro =
273 CU.getContaingFile().Dwarf->getDebugMacinfo();
274 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
275 return 0;
277 DebugInfoOutputSection.notePatchWithOffsetUpdate(
278 DebugOffsetPatch{AttrOutOffset, &CU.getOrCreateSectionDescriptor(
279 DebugSectionKind::DebugMacinfo)},
280 PatchesOffsets);
282 } else if (AttrSpec.Attr == dwarf::DW_AT_macros) {
283 if (std::optional<uint64_t> Offset = Val.getAsSectionOffset()) {
284 const DWARFDebugMacro *Macro =
285 CU.getContaingFile().Dwarf->getDebugMacro();
286 if (Macro == nullptr || !Macro->hasEntryForOffset(*Offset))
287 return 0;
289 DebugInfoOutputSection.notePatchWithOffsetUpdate(
290 DebugOffsetPatch{AttrOutOffset, &CU.getOrCreateSectionDescriptor(
291 DebugSectionKind::DebugMacro)},
292 PatchesOffsets);
294 } else if (AttrSpec.Attr == dwarf::DW_AT_stmt_list) {
295 DebugInfoOutputSection.notePatchWithOffsetUpdate(
296 DebugOffsetPatch{AttrOutOffset, &CU.getOrCreateSectionDescriptor(
297 DebugSectionKind::DebugLine)},
298 PatchesOffsets);
299 } else if (AttrSpec.Attr == dwarf::DW_AT_str_offsets_base) {
300 DebugInfoOutputSection.notePatchWithOffsetUpdate(
301 DebugOffsetPatch{
302 AttrOutOffset,
303 &CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugStrOffsets),
304 true},
305 PatchesOffsets);
307 // Use size of .debug_str_offsets header as attribute value. The offset
308 // to .debug_str_offsets would be added later while patching.
309 AttrInfo.HasStringOffsetBaseAttr = true;
310 return Generator
311 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
312 CU.getDebugStrOffsetsHeaderSize())
313 .second;
316 uint64_t Value;
317 if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly) {
318 if (auto OptionalValue = Val.getAsUnsignedConstant())
319 Value = *OptionalValue;
320 else if (auto OptionalValue = Val.getAsSignedConstant())
321 Value = *OptionalValue;
322 else if (auto OptionalValue = Val.getAsSectionOffset())
323 Value = *OptionalValue;
324 else {
325 CU.warn("unsupported scalar attribute form. Dropping attribute.",
326 InputDieEntry);
327 return 0;
330 if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
331 AttrInfo.IsDeclaration = true;
333 if (AttrSpec.Form == dwarf::DW_FORM_loclistx)
334 return Generator.addLocListAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
335 .second;
337 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Value)
338 .second;
341 dwarf::Form ResultingForm = AttrSpec.Form;
342 if (AttrSpec.Form == dwarf::DW_FORM_rnglistx) {
343 // DWARFLinker does not generate .debug_addr table. Thus we need to change
344 // all "addrx" related forms to "addr" version. Change DW_FORM_rnglistx
345 // to DW_FORM_sec_offset here.
346 std::optional<uint64_t> Index = Val.getAsSectionOffset();
347 if (!Index) {
348 CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
349 return 0;
351 std::optional<uint64_t> Offset = CU.getOrigUnit().getRnglistOffset(*Index);
352 if (!Offset) {
353 CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
354 return 0;
357 Value = *Offset;
358 ResultingForm = dwarf::DW_FORM_sec_offset;
359 } else if (AttrSpec.Form == dwarf::DW_FORM_loclistx) {
360 // DWARFLinker does not generate .debug_addr table. Thus we need to change
361 // all "addrx" related forms to "addr" version. Change DW_FORM_loclistx
362 // to DW_FORM_sec_offset here.
363 std::optional<uint64_t> Index = Val.getAsSectionOffset();
364 if (!Index) {
365 CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
366 return 0;
368 std::optional<uint64_t> Offset = CU.getOrigUnit().getLoclistOffset(*Index);
369 if (!Offset) {
370 CU.warn("cann't read the attribute. Dropping.", InputDieEntry);
371 return 0;
374 Value = *Offset;
375 ResultingForm = dwarf::DW_FORM_sec_offset;
376 } else if (AttrSpec.Attr == dwarf::DW_AT_high_pc &&
377 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) {
378 std::optional<uint64_t> LowPC = CU.getLowPc();
379 if (!LowPC)
380 return 0;
381 // Dwarf >= 4 high_pc is an size, not an address.
382 Value = CU.getHighPc() - *LowPC;
383 } else if (AttrSpec.Form == dwarf::DW_FORM_sec_offset)
384 Value = *Val.getAsSectionOffset();
385 else if (AttrSpec.Form == dwarf::DW_FORM_sdata)
386 Value = *Val.getAsSignedConstant();
387 else if (auto OptionalValue = Val.getAsUnsignedConstant())
388 Value = *OptionalValue;
389 else {
390 CU.warn("unsupported scalar attribute form. Dropping attribute.",
391 InputDieEntry);
392 return 0;
395 if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
396 AttrSpec.Attr == dwarf::DW_AT_start_scope) {
397 // Create patch for the range offset value.
398 DebugInfoOutputSection.notePatchWithOffsetUpdate(
399 DebugRangePatch{{AttrOutOffset},
400 InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit},
401 PatchesOffsets);
402 AttrInfo.HasRanges = true;
403 } else if (DWARFAttribute::mayHaveLocationList(AttrSpec.Attr) &&
404 dwarf::doesFormBelongToClass(AttrSpec.Form,
405 DWARFFormValue::FC_SectionOffset,
406 CU.getOrigUnit().getVersion())) {
407 int64_t AddrAdjustmentValue = 0;
408 if (VarAddressAdjustment)
409 AddrAdjustmentValue = *VarAddressAdjustment;
410 else if (FuncAddressAdjustment)
411 AddrAdjustmentValue = *FuncAddressAdjustment;
413 // Create patch for the location offset value.
414 DebugInfoOutputSection.notePatchWithOffsetUpdate(
415 DebugLocPatch{{AttrOutOffset}, AddrAdjustmentValue}, PatchesOffsets);
416 } else if (AttrSpec.Attr == dwarf::DW_AT_addr_base) {
417 DebugInfoOutputSection.notePatchWithOffsetUpdate(
418 DebugOffsetPatch{
419 AttrOutOffset,
420 &CU.getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr),
421 true},
422 PatchesOffsets);
424 // Use size of .debug_addr header as attribute value. The offset to
425 // .debug_addr would be added later while patching.
426 return Generator
427 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form,
428 CU.getDebugAddrHeaderSize())
429 .second;
430 } else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
431 AttrInfo.IsDeclaration = true;
433 return Generator.addScalarAttribute(AttrSpec.Attr, ResultingForm, Value)
434 .second;
437 size_t DIEAttributeCloner::cloneBlockAttr(
438 const DWARFFormValue &Val,
439 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
441 size_t NumberOfPatchesAtStart = PatchesOffsets.size();
443 // If the block is a DWARF Expression, clone it into the temporary
444 // buffer using cloneExpression(), otherwise copy the data directly.
445 SmallVector<uint8_t, 32> Buffer;
446 ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
447 if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) &&
448 (Val.isFormClass(DWARFFormValue::FC_Block) ||
449 Val.isFormClass(DWARFFormValue::FC_Exprloc))) {
450 DWARFUnit &OrigUnit = CU.getOrigUnit();
451 DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
452 OrigUnit.isLittleEndian(),
453 OrigUnit.getAddressByteSize());
454 DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
455 OrigUnit.getFormParams().Format);
457 CU.cloneDieAttrExpression(Expr, Buffer, DebugInfoOutputSection,
458 VarAddressAdjustment, PatchesOffsets);
459 Bytes = Buffer;
462 // The expression location data might be updated and exceed the original size.
463 // Check whether the new data fits into the original form.
464 dwarf::Form ResultForm = AttrSpec.Form;
465 if ((ResultForm == dwarf::DW_FORM_block1 && Bytes.size() > UINT8_MAX) ||
466 (ResultForm == dwarf::DW_FORM_block2 && Bytes.size() > UINT16_MAX) ||
467 (ResultForm == dwarf::DW_FORM_block4 && Bytes.size() > UINT32_MAX))
468 ResultForm = dwarf::DW_FORM_block;
470 size_t FinalAttributeSize;
471 if (AttrSpec.Form == dwarf::DW_FORM_exprloc)
472 FinalAttributeSize =
473 Generator.addLocationAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
474 else
475 FinalAttributeSize =
476 Generator.addBlockAttribute(AttrSpec.Attr, ResultForm, Bytes).second;
478 // Update patches offsets with the size of length field for Bytes.
479 for (size_t Idx = NumberOfPatchesAtStart; Idx < PatchesOffsets.size();
480 Idx++) {
481 assert(FinalAttributeSize > Bytes.size());
482 *PatchesOffsets[Idx] +=
483 (AttrOutOffset + (FinalAttributeSize - Bytes.size()));
486 return FinalAttributeSize;
489 size_t DIEAttributeCloner::cloneAddressAttr(
490 const DWARFFormValue &Val,
491 const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) {
492 if (AttrSpec.Attr == dwarf::DW_AT_low_pc)
493 AttrInfo.HasLowPc = true;
495 if (CU.getGlobalData().getOptions().UpdateIndexTablesOnly)
496 return Generator
497 .addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, Val.getRawUValue())
498 .second;
500 // Cloned Die may have address attributes relocated to a
501 // totally unrelated value. This can happen:
502 // - If high_pc is an address (Dwarf version == 2), then it might have been
503 // relocated to a totally unrelated value (because the end address in the
504 // object file might be start address of another function which got moved
505 // independently by the linker).
506 // - If address relocated in an inline_subprogram that happens at the
507 // beginning of its inlining function.
508 // To avoid above cases and to not apply relocation twice (in
509 // applyValidRelocs and here), read address attribute from InputDIE and apply
510 // Info.PCOffset here.
512 std::optional<DWARFFormValue> AddrAttribute =
513 CU.find(InputDieEntry, AttrSpec.Attr);
514 if (!AddrAttribute)
515 llvm_unreachable("Cann't find attribute");
517 std::optional<uint64_t> Addr = AddrAttribute->getAsAddress();
518 if (!Addr) {
519 CU.warn("cann't read address attribute value.");
520 return 0;
523 if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
524 AttrSpec.Attr == dwarf::DW_AT_low_pc) {
525 if (std::optional<uint64_t> LowPC = CU.getLowPc())
526 Addr = *LowPC;
527 else
528 return 0;
529 } else if (InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
530 AttrSpec.Attr == dwarf::DW_AT_high_pc) {
531 if (uint64_t HighPc = CU.getHighPc())
532 Addr = HighPc;
533 else
534 return 0;
535 } else {
536 if (VarAddressAdjustment)
537 *Addr += *VarAddressAdjustment;
538 else if (FuncAddressAdjustment)
539 *Addr += *FuncAddressAdjustment;
542 if (AttrSpec.Form == dwarf::DW_FORM_addr) {
543 return Generator.addScalarAttribute(AttrSpec.Attr, AttrSpec.Form, *Addr)
544 .second;
547 return Generator
548 .addScalarAttribute(AttrSpec.Attr, dwarf::Form::DW_FORM_addrx,
549 CU.getDebugAddrIndex(*Addr))
550 .second;
553 unsigned DIEAttributeCloner::finalizeAbbreviations(bool HasChildrenToClone) {
554 size_t SizeOfAbbreviationNumber =
555 Generator.finalizeAbbreviations(HasChildrenToClone);
557 // We need to update patches offsets after we know the size of the
558 // abbreviation number.
559 updatePatchesWithSizeOfAbbreviationNumber(SizeOfAbbreviationNumber);
561 // Add the size of the abbreviation number to the output offset.
562 AttrOutOffset += SizeOfAbbreviationNumber;
564 return AttrOutOffset;
567 } // end of namespace dwarflinker_parallel
568 } // namespace llvm