diff --git a/lld/test/ELF/riscv-relax-align-rvc.s b/lld/test/ELF/riscv-relax-align-rvc.s --- a/lld/test/ELF/riscv-relax-align-rvc.s +++ b/lld/test/ELF/riscv-relax-align-rvc.s @@ -50,7 +50,7 @@ # CHECK-NEXT: c.addi a0, 8 # CHECK-EMPTY: -# CHECK: <.text2>: +# CHECK: : # CHECK-NEXT: addi a0, a1, 1 # CHECK-NEXT: c.addi a0, 1 # CHECK-NEXT: c.nop @@ -81,6 +81,7 @@ .size _start, . - _start .section .text2,"ax" +text2: .balign 16 addi a0, a1, 1 c.addi a0, 1 diff --git a/lld/test/ELF/riscv-relax-call.s b/lld/test/ELF/riscv-relax-call.s --- a/lld/test/ELF/riscv-relax-call.s +++ b/lld/test/ELF/riscv-relax-call.s @@ -47,16 +47,16 @@ # NORVC-NEXT: jal ra, 0x10420 # NORVC-EMPTY: -# NORVC-LABEL: <.mid>: +# NORVC-LABEL: : # NORVC-NEXT: 10800: jal ra, {{.*}} <_start> # NORVC-NEXT: jal ra, {{.*}} <_start> # NORVC-EMPTY: -# NORVC-LABEL: <.mid2>: +# NORVC-LABEL: : # NORVC-NEXT: 1080c: jal ra, {{.*}} <_start> # NORVC-EMPTY: -# NORVC-LABEL: <.high>: +# NORVC-LABEL: : # NORVC-NEXT: 110006: auipc ra, 1048320 # NORVC-NEXT: jalr ra, -6(ra) # NORVC-NEXT: auipc ra, 1048320 @@ -87,18 +87,18 @@ # RVC-NEXT: c.jr ra # RVC-EMPTY: -# RVC-LABEL: <.mid>: +# RVC-LABEL: : # RVC32-NEXT: 10800: c.jal {{.*}} <_start> # RVC64-NEXT: 10800: jal ra, {{.*}} <_start> # RVC-NEXT: jal ra, {{.*}} <_start> # RVC-EMPTY: -# RVC-LABEL: <.mid2>: +# RVC-LABEL: : # RVC32-NEXT: 1080a: jal ra, {{.*}} <_start> # RVC64-NEXT: 1080c: jal ra, {{.*}} <_start> # RVC-EMPTY: -# RVC-LABEL: <.high>: +# RVC-LABEL: : # RVC32-NEXT: 110000: jal ra, 0x10000 <_start> # RVC32-NEXT: auipc ra, 1048320 # RVC32-NEXT: jalr ra, -4(ra) @@ -134,13 +134,16 @@ _start_end: .section .mid,"ax",@progbits +mid: call _start@plt # rv32c: c.jal; rv64c: jal call _start@plt .section .mid2,"ax",@progbits +mid2: call _start@plt .section .high,"ax",@progbits +high: call _start@plt # relaxable for %t/32c call _start@plt # not relaxed diff --git a/lld/test/ELF/riscv-relax-call2.s b/lld/test/ELF/riscv-relax-call2.s --- a/lld/test/ELF/riscv-relax-call2.s +++ b/lld/test/ELF/riscv-relax-call2.s @@ -20,12 +20,12 @@ # CHECK-NEXT: jalr zero, -4(t1) # CHECK-EMPTY: -# CHECK-LABEL: <.mid>: +# CHECK-LABEL: : # CHECK-NEXT: jal zero, 0x101000 # CHECK-NEXT: c.j 0x101000 # CHECK-EMPTY: -# CHECK2-LABEL: <.mid>: +# CHECK2-LABEL: : # CHECK2-NEXT: auipc t1, 0 # CHECK2-NEXT: jalr zero, 0(t1) # CHECK2-NEXT: auipc t1, 0 @@ -41,6 +41,7 @@ tail abs # not relaxed .section .mid,"ax",@progbits +mid: .balign 16 tail ifunc@plt # not relaxed tail ifunc@plt diff --git a/lld/test/ELF/riscv-tls-le.s b/lld/test/ELF/riscv-tls-le.s --- a/lld/test/ELF/riscv-tls-le.s +++ b/lld/test/ELF/riscv-tls-le.s @@ -49,7 +49,7 @@ # LE-NEXT: sw a0, -2048(a4) # LE-EMPTY: -# LE-RELAX: <.text>: +# LE-RELAX: : # LE-RELAX-NEXT: addi a1, tp, 8 # LE-RELAX-NEXT: addi a2, tp, 2044 # LE-RELAX-NEXT: addi a0, a0, 1 @@ -60,6 +60,7 @@ # LE-RELAX-NEXT: sw a0, -2048(a4) # LE-RELAX-EMPTY: +text: lui a1, %tprel_hi(.LANCHOR0) add a1, a1, tp, %tprel_add(.LANCHOR0) addi a1, a1, %tprel_lo(.LANCHOR0) diff --git a/lld/test/ELF/riscv-variant-cc.s b/lld/test/ELF/riscv-variant-cc.s --- a/lld/test/ELF/riscv-variant-cc.s +++ b/lld/test/ELF/riscv-variant-cc.s @@ -45,7 +45,7 @@ # CHECK5: 0 NOTYPE GLOBAL DEFAULT [VARIANT_CC] UND func_global_undef # CHECK5-NEXT: 0 NOTYPE GLOBAL DEFAULT [VARIANT_CC] [[#]] func_global_def # CHECK5-NEXT: 0 IFUNC GLOBAL DEFAULT [VARIANT_CC] [[#]] ifunc_global_def -# CHECK5: Symbol table '.symtab' contains 9 entries: +# CHECK5: Symbol table '.symtab' contains 10 entries: # CHECK5: 0 NOTYPE LOCAL DEFAULT [VARIANT_CC] [[#]] func_local # CHECK5-NEXT: 0 IFUNC LOCAL DEFAULT [VARIANT_CC] [[#]] ifunc_local # CHECK5: 0 NOTYPE LOCAL HIDDEN [VARIANT_CC] [[#]] func_global_hidden diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.h @@ -16,12 +16,27 @@ class RISCVELFStreamer : public MCELFStreamer { void reset() override; + void emitDataMappingSymbol(); + void emitInstructionsMappingSymbol(); + void emitMappingSymbol(StringRef Name); + + enum ElfMappingSymbol { EMS_None, EMS_Instructions, EMS_Data }; + + int64_t MappingSymbolCounter; + DenseMap LastMappingSymbols; + ElfMappingSymbol LastEMS; public: RISCVELFStreamer(MCContext &C, std::unique_ptr MAB, std::unique_ptr MOW, std::unique_ptr MCE) : MCELFStreamer(C, std::move(MAB), std::move(MOW), std::move(MCE)) {} + + void changeSection(MCSection *Section, const MCExpr *Subsection) override; + void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void emitBytes(StringRef Data) override; + void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc) override; + void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; }; namespace llvm { diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -125,6 +125,66 @@ void RISCVELFStreamer::reset() { static_cast(getTargetStreamer())->reset(); MCELFStreamer::reset(); + MappingSymbolCounter = 0; + LastMappingSymbols.clear(); + LastEMS = EMS_None; +} + +void RISCVELFStreamer::emitDataMappingSymbol() { + if (LastEMS == EMS_Data) + return; + emitMappingSymbol("$d"); + LastEMS = EMS_Data; +} + +void RISCVELFStreamer::emitInstructionsMappingSymbol() { + if (LastEMS == EMS_Instructions) + return; + emitMappingSymbol("$x"); + LastEMS = EMS_Instructions; +} + +void RISCVELFStreamer::emitMappingSymbol(StringRef Name) { + auto *Symbol = cast(getContext().getOrCreateSymbol( + Name + "." + Twine(MappingSymbolCounter++))); + emitLabel(Symbol); + Symbol->setType(ELF::STT_NOTYPE); + Symbol->setBinding(ELF::STB_LOCAL); + Symbol->setExternal(false); +} + +void RISCVELFStreamer::changeSection(MCSection *Section, + const MCExpr *Subsection) { + // We have to keep track of the mapping symbol state of any sections we + // use. Each one should start off as EMS_None, which is provided as the + // default constructor by DenseMap::lookup. + LastMappingSymbols[getPreviousSection().first] = LastEMS; + LastEMS = LastMappingSymbols.lookup(Section); + + MCELFStreamer::changeSection(Section, Subsection); +} + +void RISCVELFStreamer::emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + emitInstructionsMappingSymbol(); + MCELFStreamer::emitInstruction(Inst, STI); +} + +void RISCVELFStreamer::emitBytes(StringRef Data) { + emitDataMappingSymbol(); + MCELFStreamer::emitBytes(Data); +} + +void RISCVELFStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, + SMLoc Loc) { + emitDataMappingSymbol(); + MCELFStreamer::emitFill(NumBytes, FillValue, Loc); +} + +void RISCVELFStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, + SMLoc Loc) { + emitDataMappingSymbol(); + MCELFStreamer::emitValueImpl(Value, Size, Loc); } namespace llvm { diff --git a/llvm/test/MC/RISCV/align.s b/llvm/test/MC/RISCV/align.s --- a/llvm/test/MC/RISCV/align.s +++ b/llvm/test/MC/RISCV/align.s @@ -128,9 +128,10 @@ .word 9 # Check that the initial alignment is properly handled when using .option to # disable the C extension. This used to crash. -# C-OR-ZCA-EXT-RELAX-INST: <.text2>: +# C-OR-ZCA-EXT-RELAX-INST: : # C-OR-ZCA-EXT-RELAX-INST-NEXT: add a0, a0, a1 .section .text2, "x" .option norvc +text2: .balign 4 add a0, a0, a1 diff --git a/llvm/test/MC/RISCV/mapping-across-sections.s b/llvm/test/MC/RISCV/mapping-across-sections.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/mapping-across-sections.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc -triple=riscv32 -filetype=obj < %s | llvm-objdump -t - | FileCheck %s +# RUN: llvm-mc -triple=riscv64 -filetype=obj < %s | llvm-objdump -t - | FileCheck %s + + .text + nop + +# .wibble should *not* inherit .text's mapping symbol. It's a completely +# different section. + .section .wibble + nop + +# A setion should be able to start with a $d + .section .starts_data + .word 42 + +# Changing back to .text should not emit a redundant $x + .text + nop + +# With all those constraints, we want: +# + .text to have $x at 0 and no others +# + .wibble to have $x at 0 +# + .starts_data to have $d at 0 + +# CHECK: {{0+}} l .text {{0+}} $x +# CHECK-NEXT: {{0+}} l .wibble {{0+}} $x +# CHECK-NEXT: {{0+}} l .starts_data {{0+}} $d +# CHECK-NOT: ${{[dx]}} + diff --git a/llvm/test/MC/RISCV/mapping-within-section.s b/llvm/test/MC/RISCV/mapping-within-section.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/mapping-within-section.s @@ -0,0 +1,23 @@ +# RUN: llvm-mc -triple=riscv32 -filetype=obj %s | llvm-objdump -t - | FileCheck %s +# RUN: llvm-mc -triple=riscv64 -filetype=obj %s | llvm-objdump -t - | FileCheck %s + + .text +# $x at 0x0000 + nop +# $d at 0x0004 + .ascii "012" + .byte 1 + .hword 2 + .word 4 + .single 4.0 + .double 8.0 + .space 10 + .zero 3 + .fill 10, 2, 42 + .org 100, 12 +# $x at 0x0064 + nop + +# CHECK: {{0+}}00 l .text {{0+}} $x +# CHECK-NEXT: {{0+}}04 l .text {{0+}} $d +# CHECK-NEXT: {{0+}}64 l .text {{0+}} $x diff --git a/llvm/test/MC/RISCV/nop-slide.s b/llvm/test/MC/RISCV/nop-slide.s --- a/llvm/test/MC/RISCV/nop-slide.s +++ b/llvm/test/MC/RISCV/nop-slide.s @@ -3,25 +3,25 @@ # RUN: llvm-mc -triple riscv64 -mattr -c,-relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s # RUN: llvm-mc -triple riscv64 -mattr -c,+relax -filetype obj -o - %s | llvm-objdump -d - | FileCheck %s +text: .balign 4 .byte 0 .balign 4 auipc a0, 0 -# CHECK-RVC-NORELAX: 0000000000000000 <.text>: -# CHECK-RVC-NORELAX-NEXT: 0: 00 00 unimp -# CHECK-RVC-NORELAX-NEXT: 2: 01 00 nop -# CHECK-RVC-NORELAX-NEXT: 4: 17 05 00 00 auipc a0, 0 +# CHECK-RVC-NORELAX: 0000000000000000 : +# CHECK-RVC-NORELAX: 0: 00 00 unimp +# CHECK-RVC-NORELAX: 2: 01 00 nop +# CHECK-RVC-NORELAX: 4: 17 05 00 00 auipc a0, 0 -# CHECK-RVC-RELAX: 0000000000000000 <.text>: -# CHECK-RVC-RELAX-NEXT: 0: 01 00 nop -# CHECK-RVC-RELAX-NEXT: 2: 00 01 addi s0, sp, 128 -# CHECK-RVC-RELAX-NEXT: 4: 00 17 addi s0, sp, 928 -# CHECK-RVC-RELAX-NEXT: 6: 05 00 c.nop 1 -# CHECK-RVC-RELAX-NEXT: 8: 00 +# CHECK-RVC-RELAX: 0000000000000000 : +# CHECK-RVC-RELAX: 0: 01 00 nop +# CHECK-RVC-RELAX: 2: 00 01 addi s0, sp, 128 +# CHECK-RVC-RELAX: 4: 00 17 addi s0, sp, 928 +# CHECK-RVC-RELAX: 5: 17 05 00 00 auipc a0, 0 -# CHECK: 0000000000000000 <.text>: -# CHECK-NEXT: 0: 00 00 -# CHECK-NEXT: 2: 00 00 -# CHECK-NEXT: 4: 17 05 00 00 auipc a0, 0 +# CHECK: 0000000000000000 : +# CHECK: 0: 00 00 +# CHECK: 2: 00 00 +# CHECK: 4: 17 05 00 00 auipc a0, 0