diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -123,6 +123,8 @@ /// This is used to emit bytes in \p Data as sequence of .byte directives. virtual void emitRawBytes(StringRef Data); + virtual void emitConstantPools(); + virtual void finish(); }; @@ -165,7 +167,7 @@ virtual void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value); - void finish() override; + void emitConstantPools() override; /// Reset any state between object emissions, i.e. the equivalent of /// MCStreamer's reset method. diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1815,6 +1815,11 @@ } } + // This needs to happen before emitting debug information since that can end + // arbitrary sections. + if (auto *TS = OutStreamer->getTargetStreamer()) + TS->emitConstantPools(); + // Finalize debug and EH information. for (const HandlerInfo &HI : Handlers) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -1052,11 +1052,14 @@ } } } - // Finalize the output stream if there are no errors and if the client wants // us to. - if (!HadError && !NoFinalize) + if (!HadError && !NoFinalize) { + if (auto *TS = Out.getTargetStreamer()) + TS->emitConstantPools(); + Out.Finish(Lexer.getLoc()); + } return HadError || getContext().hadError(); } diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -53,6 +53,8 @@ void MCTargetStreamer::finish() {} +void MCTargetStreamer::emitConstantPools() {} + void MCTargetStreamer::changeSection(const MCSection *CurSection, MCSection *Section, const MCExpr *Subsection, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h @@ -23,6 +23,7 @@ ~AArch64TargetStreamer() override; void finish() override; + void emitConstantPools() override; /// Callback used to implement the ldr= pseudo. /// Add a new entry to the constant pool for the current section and return an diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp @@ -48,11 +48,13 @@ ConstantPools->emitForCurrentSection(Streamer); } +void AArch64TargetStreamer::emitConstantPools() { + ConstantPools->emitAll(Streamer); +} + // finish() - write out any non-empty assembler constant pools and // write out note.gnu.properties if need. void AArch64TargetStreamer::finish() { - ConstantPools->emitAll(Streamer); - if (MarkBTIProperty) emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI); } diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -43,7 +43,9 @@ } // finish() - write out any non-empty assembler constant pools. -void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); } +void ARMTargetStreamer::emitConstantPools() { + ConstantPools->emitAll(Streamer); +} // reset() - Reset any state void ARMTargetStreamer::reset() {} diff --git a/llvm/test/CodeGen/ARM/arange-ldr.ll b/llvm/test/CodeGen/ARM/arange-ldr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/arange-ldr.ll @@ -0,0 +1,31 @@ +; RUN: llc %s -o - -generate-arange-section | FileCheck %s + +; Make sure that emitting constants for ldr and emitting arange work together. +; Emitting constants must come before emitting aranges since emitting aranges can end arbitrary sections. + +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "armv7-unknown-linux-android21" + +; CHECK: ldr r7, .Ltmp[[#TMP:]] + +; CHECK: .Ltmp[[#TMP]]: +; CHECK-NEXT: .long 83040 + +; CHECK: .section .debug_aranges + +define dso_local void @a() local_unnamed_addr !dbg !4 { +entry: + call void asm sideeffect " ldr r7, =${0:c}\0A", "i"(i32 83040) + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "/tmp/a.c", directory: "/tmp/") +!2 = !{} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "a", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!5 = !DIFile(filename: "/tmp/a.c", directory: "") +!6 = !DISubroutineType(types: !2)