Skip to content

Commit 286c92a

Browse files
MQ-mengqingAmi-zhang
authored andcommitted
[LoongArch] Add relaxDwarfLineAddr and relaxDwarfCFA to handle the mutable label diff in dwarfinfo (llvm#77728)
When linker-relaxation is enabled, part of the label diff in dwarfinfo cannot be computed before static link. Refer to RISCV, we add the relaxDwarfLineAddr and relaxDwarfCFA to add relocations for these label diffs. Calculate whether the label diff is mutable. For immutable label diff, return false and do the other works by its parent function. (cherry picked from commit ed7f4ed) Change-Id: Iae5bad958c6d1a71dac1672f5f03991eaeea6d22
1 parent 8d7b718 commit 286c92a

File tree

5 files changed

+274
-2
lines changed

5 files changed

+274
-2
lines changed

llvm/lib/Object/RelocationResolver.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ static bool supportsLoongArch(uint64_t Type) {
539539
case ELF::R_LARCH_32:
540540
case ELF::R_LARCH_32_PCREL:
541541
case ELF::R_LARCH_64:
542+
case ELF::R_LARCH_ADD6:
543+
case ELF::R_LARCH_SUB6:
542544
case ELF::R_LARCH_ADD8:
543545
case ELF::R_LARCH_SUB8:
544546
case ELF::R_LARCH_ADD16:
@@ -564,6 +566,10 @@ static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S,
564566
return (S + Addend - Offset) & 0xFFFFFFFF;
565567
case ELF::R_LARCH_64:
566568
return S + Addend;
569+
case ELF::R_LARCH_ADD6:
570+
return (LocData & 0xC0) | ((LocData + S + Addend) & 0x3F);
571+
case ELF::R_LARCH_SUB6:
572+
return (LocData & 0xC0) | ((LocData - (S + Addend)) & 0x3F);
567573
case ELF::R_LARCH_ADD8:
568574
return (LocData + (S + Addend)) & 0xFF;
569575
case ELF::R_LARCH_SUB8:
@@ -880,8 +886,10 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
880886

881887
if (GetRelSectionType() == ELF::SHT_RELA) {
882888
Addend = getELFAddend(R);
883-
// RISCV relocations use both LocData and Addend.
884-
if (Obj->getArch() != Triple::riscv32 &&
889+
// LoongArch and RISCV relocations use both LocData and Addend.
890+
if (Obj->getArch() != Triple::loongarch32 &&
891+
Obj->getArch() != Triple::loongarch64 &&
892+
Obj->getArch() != Triple::riscv32 &&
885893
Obj->getArch() != Triple::riscv64)
886894
LocData = 0;
887895
}

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212

1313
#include "LoongArchAsmBackend.h"
1414
#include "LoongArchFixupKinds.h"
15+
#include "llvm/MC/MCAsmInfo.h"
1516
#include "llvm/MC/MCAsmLayout.h"
1617
#include "llvm/MC/MCAssembler.h"
1718
#include "llvm/MC/MCContext.h"
1819
#include "llvm/MC/MCELFObjectWriter.h"
1920
#include "llvm/MC/MCValue.h"
2021
#include "llvm/Support/Endian.h"
2122
#include "llvm/Support/EndianStream.h"
23+
#include "llvm/Support/LEB128.h"
2224

2325
#define DEBUG_TYPE "loongarch-asmbackend"
2426

@@ -235,6 +237,133 @@ std::pair<bool, bool> LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF,
235237
return std::make_pair(true, true);
236238
}
237239

240+
bool LoongArchAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
241+
MCAsmLayout &Layout,
242+
bool &WasRelaxed) const {
243+
MCContext &C = Layout.getAssembler().getContext();
244+
245+
int64_t LineDelta = DF.getLineDelta();
246+
const MCExpr &AddrDelta = DF.getAddrDelta();
247+
SmallVectorImpl<char> &Data = DF.getContents();
248+
SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();
249+
size_t OldSize = Data.size();
250+
251+
int64_t Value;
252+
if (AddrDelta.evaluateAsAbsolute(Value, Layout))
253+
return false;
254+
bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout);
255+
assert(IsAbsolute && "CFA with invalid expression");
256+
(void)IsAbsolute;
257+
258+
Data.clear();
259+
Fixups.clear();
260+
raw_svector_ostream OS(Data);
261+
262+
// INT64_MAX is a signal that this is actually a DW_LNE_end_sequence.
263+
if (LineDelta != INT64_MAX) {
264+
OS << uint8_t(dwarf::DW_LNS_advance_line);
265+
encodeSLEB128(LineDelta, OS);
266+
}
267+
268+
unsigned Offset;
269+
std::pair<MCFixupKind, MCFixupKind> FK;
270+
271+
// According to the DWARF specification, the `DW_LNS_fixed_advance_pc` opcode
272+
// takes a single unsigned half (unencoded) operand. The maximum encodable
273+
// value is therefore 65535. Set a conservative upper bound for relaxation.
274+
if (Value > 60000) {
275+
unsigned PtrSize = C.getAsmInfo()->getCodePointerSize();
276+
277+
OS << uint8_t(dwarf::DW_LNS_extended_op);
278+
encodeULEB128(PtrSize + 1, OS);
279+
280+
OS << uint8_t(dwarf::DW_LNE_set_address);
281+
Offset = OS.tell();
282+
assert((PtrSize == 4 || PtrSize == 8) && "Unexpected pointer size");
283+
FK = getRelocPairForSize(PtrSize == 4 ? 32 : 64);
284+
OS.write_zeros(PtrSize);
285+
} else {
286+
OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
287+
Offset = OS.tell();
288+
FK = getRelocPairForSize(16);
289+
support::endian::write<uint16_t>(OS, 0, support::little);
290+
}
291+
292+
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
293+
Fixups.push_back(MCFixup::create(Offset, MBE.getLHS(), std::get<0>(FK)));
294+
Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(FK)));
295+
296+
if (LineDelta == INT64_MAX) {
297+
OS << uint8_t(dwarf::DW_LNS_extended_op);
298+
OS << uint8_t(1);
299+
OS << uint8_t(dwarf::DW_LNE_end_sequence);
300+
} else {
301+
OS << uint8_t(dwarf::DW_LNS_copy);
302+
}
303+
304+
WasRelaxed = OldSize != Data.size();
305+
return true;
306+
}
307+
308+
bool LoongArchAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
309+
MCAsmLayout &Layout,
310+
bool &WasRelaxed) const {
311+
const MCExpr &AddrDelta = DF.getAddrDelta();
312+
SmallVectorImpl<char> &Data = DF.getContents();
313+
SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();
314+
size_t OldSize = Data.size();
315+
316+
int64_t Value;
317+
if (AddrDelta.evaluateAsAbsolute(Value, Layout))
318+
return false;
319+
bool IsAbsolute = AddrDelta.evaluateKnownAbsolute(Value, Layout);
320+
assert(IsAbsolute && "CFA with invalid expression");
321+
(void)IsAbsolute;
322+
323+
Data.clear();
324+
Fixups.clear();
325+
raw_svector_ostream OS(Data);
326+
327+
assert(
328+
Layout.getAssembler().getContext().getAsmInfo()->getMinInstAlignment() ==
329+
1 &&
330+
"expected 1-byte alignment");
331+
if (Value == 0) {
332+
WasRelaxed = OldSize != Data.size();
333+
return true;
334+
}
335+
336+
auto AddFixups = [&Fixups,
337+
&AddrDelta](unsigned Offset,
338+
std::pair<MCFixupKind, MCFixupKind> FK) {
339+
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
340+
Fixups.push_back(MCFixup::create(Offset, MBE.getLHS(), std::get<0>(FK)));
341+
Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(FK)));
342+
};
343+
344+
if (isUIntN(6, Value)) {
345+
OS << uint8_t(dwarf::DW_CFA_advance_loc);
346+
AddFixups(0, getRelocPairForSize(6));
347+
} else if (isUInt<8>(Value)) {
348+
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
349+
support::endian::write<uint8_t>(OS, 0, support::little);
350+
AddFixups(1, getRelocPairForSize(8));
351+
} else if (isUInt<16>(Value)) {
352+
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
353+
support::endian::write<uint16_t>(OS, 0, support::little);
354+
AddFixups(1, getRelocPairForSize(16));
355+
} else if (isUInt<32>(Value)) {
356+
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
357+
support::endian::write<uint32_t>(OS, 0, support::little);
358+
AddFixups(1, getRelocPairForSize(32));
359+
} else {
360+
llvm_unreachable("unsupported CFA encoding");
361+
}
362+
363+
WasRelaxed = OldSize != Data.size();
364+
return true;
365+
}
366+
238367
bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
239368
const MCSubtargetInfo *STI) const {
240369
// We mostly follow binutils' convention here: align to 4-byte boundary with a

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ class LoongArchAsmBackend : public MCAsmBackend {
6868
std::pair<bool, bool> relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
6969
int64_t &Value) const override;
7070

71+
bool relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF, MCAsmLayout &Layout,
72+
bool &WasRelaxed) const override;
73+
bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout,
74+
bool &WasRelaxed) const override;
75+
7176
bool writeNopData(raw_ostream &OS, uint64_t Count,
7277
const MCSubtargetInfo *STI) const override;
7378

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
; RUN: llc --filetype=obj --mtriple=loongarch64 --mattr=-relax %s -o %t.o
2+
; RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS-BOTH,RELOCS-NORL %s
3+
; RUN: llvm-objdump --source %t.o | FileCheck --check-prefix=SOURCE %s
4+
; RUN: llvm-dwarfdump --debug-info --debug-line %t.o | FileCheck --check-prefix=DWARF %s
5+
6+
; RUN: llc --filetype=obj --mtriple=loongarch64 --mattr=+relax %s -o %t.r.o
7+
; RUN: llvm-readobj -r %t.r.o | FileCheck --check-prefixes=RELOCS-BOTH,RELOCS-ENRL %s
8+
; RUN: llvm-objdump --source %t.r.o | FileCheck --check-prefix=SOURCE %s
9+
; RUN: llvm-dwarfdump --debug-info --debug-line %t.r.o | FileCheck --check-prefix=DWARF %s
10+
11+
; RELOCS-BOTH: Relocations [
12+
; RELOCS-BOTH-NEXT: Section ({{.*}}) .rela.text {
13+
; RELOCS-BOTH-NEXT: 0x14 R_LARCH_PCALA_HI20 sym 0x0
14+
; RELOCS-ENRL-NEXT: 0x14 R_LARCH_RELAX - 0x0
15+
; RELOCS-BOTH-NEXT: 0x18 R_LARCH_PCALA_LO12 sym 0x0
16+
; RELOCS-ENRL-NEXT: 0x18 R_LARCH_RELAX - 0x0
17+
; RELOCS-BOTH-NEXT: }
18+
; RELOCS-BOTH: Section ({{.*}}) .rela.debug_frame {
19+
; RELOCS-NORL-NEXT: 0x1C R_LARCH_32 .debug_frame 0x0
20+
; RELOCS-NORL-NEXT: 0x20 R_LARCH_64 .text 0x0
21+
; RELOCS-ENRL-NEXT: 0x1C R_LARCH_32 <null> 0x0
22+
; RELOCS-ENRL-NEXT: 0x20 R_LARCH_64 <null> 0x0
23+
; RELOCS-ENRL-NEXT: 0x28 R_LARCH_ADD64 <null> 0x0
24+
; RELOCS-ENRL-NEXT: 0x28 R_LARCH_SUB64 <null> 0x0
25+
; RELOCS-ENRL-NEXT: 0x3F R_LARCH_ADD6 <null> 0x0
26+
; RELOCS-ENRL-NEXT: 0x3F R_LARCH_SUB6 <null> 0x0
27+
; RELOCS-BOTH-NEXT: }
28+
; RELOCS-BOTH: Section ({{.*}}) .rela.debug_line {
29+
; RELOCS-BOTH-NEXT: 0x22 R_LARCH_32 .debug_line_str 0x0
30+
; RELOCS-BOTH-NEXT: 0x31 R_LARCH_32 .debug_line_str 0x2
31+
; RELOCS-BOTH-NEXT: 0x46 R_LARCH_32 .debug_line_str 0x1B
32+
; RELOCS-NORL-NEXT: 0x4F R_LARCH_64 .text 0x0
33+
; RELOCS-ENRL-NEXT: 0x4F R_LARCH_64 <null> 0x0
34+
; RELOCS-ENRL-NEXT: 0x5F R_LARCH_ADD16 <null> 0x0
35+
; RELOCS-ENRL-NEXT: 0x5F R_LARCH_SUB16 <null> 0x0
36+
; RELOCS-BOTH-NEXT: }
37+
; RELOCS-BOTH-NEXT: ]
38+
39+
; SOURCE: 0000000000000000 <foo>:
40+
; SOURCE: ; {
41+
; SOURCE: ; asm volatile(
42+
; SOURCE: ; return 0;
43+
44+
; DWARF: DW_AT_producer ("clang")
45+
; DWARF: DW_AT_name ("dwarf-loongarch-relocs.c")
46+
; DWARF: DW_AT_comp_dir (".")
47+
; DWARF: DW_AT_name ("foo")
48+
; DWARF-NEXT: DW_AT_decl_file ("{{.*}}dwarf-loongarch-relocs.c")
49+
; DWARF-NEXT: DW_AT_decl_line (1)
50+
; DWARF-NEXT: DW_AT_type (0x00000032 "int")
51+
; DWARF: DW_AT_name ("int")
52+
; DWARF-NEXT: DW_AT_encoding (DW_ATE_signed)
53+
; DWARF-NEXT: DW_AT_byte_size (0x04)
54+
; DWARF: .debug_line contents:
55+
; DWARF-NEXT: debug_line[0x00000000]
56+
; DWARF-NEXT: Line table prologue:
57+
; DWARF-NEXT: total_length: {{.*}}
58+
; DWARF-NEXT: format: DWARF32
59+
; DWARF-NEXT: version: 5
60+
; DWARF-NEXT: address_size: 8
61+
; DWARF-NEXT: seg_select_size: 0
62+
; DWARF-NEXT: prologue_length: 0x0000003e
63+
; DWARF-NEXT: min_inst_length: 1
64+
; DWARF-NEXT: max_ops_per_inst: 1
65+
; DWARF-NEXT: default_is_stmt: 1
66+
; DWARF-NEXT: line_base: -5
67+
; DWARF-NEXT: line_range: 14
68+
; DWARF-NEXT: opcode_base: 13
69+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_copy] = 0
70+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_advance_pc] = 1
71+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_advance_line] = 1
72+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_file] = 1
73+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_column] = 1
74+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_negate_stmt] = 0
75+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_basic_block] = 0
76+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_const_add_pc] = 0
77+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1
78+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_prologue_end] = 0
79+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
80+
; DWARF-NEXT: standard_opcode_lengths[DW_LNS_set_isa] = 1
81+
; DWARF-NEXT: include_directories[ 0] = "."
82+
; DWARF-NEXT: file_names[ 0]:
83+
; DWARF-NEXT: name: "dwarf-loongarch-relocs.c"
84+
; DWARF-NEXT: dir_index: 0
85+
; DWARF-NEXT: md5_checksum: f44d6d71bc4da58b4abe338ca507c007
86+
; DWARF-NEXT: source: "{{.*}}"
87+
; DWARF-EMPTY:
88+
; DWARF-NEXT: Address Line Column File ISA Discriminator OpIndex Flags
89+
; DWARF-NEXT: ------------------ ------ ------ ------ --- ------------- ------- -------------
90+
; DWARF-NEXT: 0x0000000000000000 2 0 0 0 0 0 is_stmt
91+
; DWARF-NEXT: 0x0000000000000010 3 3 0 0 0 0 is_stmt prologue_end
92+
; DWARF-NEXT: 0x0000000000000020 10 3 0 0 0 0 is_stmt
93+
; DWARF-NEXT: 0x000000000000002c 10 3 0 0 0 0 epilogue_begin
94+
; DWARF-NEXT: 0x0000000000000034 10 3 0 0 0 0 end_sequence
95+
96+
; ModuleID = 'dwarf-loongarch-relocs.c'
97+
source_filename = "dwarf-loongarch-relocs.c"
98+
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
99+
target triple = "loongarch64"
100+
101+
; Function Attrs: noinline nounwind optnone
102+
define dso_local signext i32 @foo() #0 !dbg !8 {
103+
call void asm sideeffect ".cfi_remember_state\0A\09.cfi_adjust_cfa_offset 16\0A\09nop\0A\09la.pcrel $$t0, sym\0A\09nop\0A\09.cfi_restore_state\0A\09", ""() #1, !dbg !12, !srcloc !13
104+
ret i32 0, !dbg !14
105+
}
106+
107+
attributes #0 = { noinline nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="loongarch64" "target-features"="+64bit,+d,+f,+ual" }
108+
attributes #1 = { nounwind }
109+
110+
!llvm.dbg.cu = !{!0}
111+
!llvm.module.flags = !{!2, !3, !4, !5, !6}
112+
!llvm.ident = !{!7}
113+
114+
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
115+
!1 = !DIFile(filename: "dwarf-loongarch-relocs.c", directory: ".", checksumkind: CSK_MD5, checksum: "f44d6d71bc4da58b4abe338ca507c007", source: "int foo()\0A{\0A asm volatile(\0A \22.cfi_remember_state\\n\\t\22\0A \22.cfi_adjust_cfa_offset 16\\n\\t\22\0A \22nop\\n\\t\22\0A \22la.pcrel $t0, sym\\n\\t\22\0A \22nop\\n\\t\22\0A \22.cfi_restore_state\\n\\t\22);\0A return 0;\0A}\0A")
116+
!2 = !{i32 7, !"Dwarf Version", i32 5}
117+
!3 = !{i32 2, !"Debug Info Version", i32 3}
118+
!4 = !{i32 1, !"wchar_size", i32 4}
119+
!5 = !{i32 7, !"direct-access-external-data", i32 0}
120+
!6 = !{i32 7, !"frame-pointer", i32 2}
121+
!7 = !{!"clang"}
122+
!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !9, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0)
123+
!9 = !DISubroutineType(types: !10)
124+
!10 = !{!11}
125+
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
126+
!12 = !DILocation(line: 3, column: 3, scope: !8)
127+
!13 = !{i64 34, i64 56, i64 92, i64 106, i64 134, i64 148, i64 177}
128+
!14 = !DILocation(line: 10, column: 3, scope: !8)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
if "LoongArch" not in config.root.targets:
2+
config.unsupported = True

0 commit comments

Comments
 (0)