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 @@ -92,6 +92,8 @@ void finishAttributeSection() override; size_t calculateContentSize() const; + void reset() override; + public: MCELFStreamer &getStreamer(); RISCVTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); 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 @@ -180,6 +180,11 @@ MCA.setELFHeaderEFlags(EFlags); } +void RISCVTargetELFStreamer::reset() { + AttributeSection = nullptr; + Contents.clear(); +} + namespace { class RISCVELFStreamer : public MCELFStreamer { static std::pair getRelocPairForSize(unsigned Size) { @@ -226,6 +231,13 @@ : !B.getName().empty()); } + void reset() override { + MCTargetStreamer &TS = *getTargetStreamer(); + RISCVTargetStreamer &RTS = static_cast(TS); + RTS.reset(); + MCELFStreamer::reset(); + } + public: RISCVELFStreamer(MCContext &C, std::unique_ptr MAB, std::unique_ptr MOW, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h @@ -23,6 +23,7 @@ public: RISCVTargetStreamer(MCStreamer &S); void finish() override; + virtual void reset(); virtual void emitDirectiveOptionPush(); virtual void emitDirectiveOptionPop(); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp @@ -22,6 +22,7 @@ RISCVTargetStreamer::RISCVTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} void RISCVTargetStreamer::finish() { finishAttributeSection(); } +void RISCVTargetStreamer::reset() {} void RISCVTargetStreamer::emitDirectiveOptionPush() {} void RISCVTargetStreamer::emitDirectiveOptionPop() {} diff --git a/llvm/test/MC/RISCV/twice.ll b/llvm/test/MC/RISCV/twice.ll new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/twice.ll @@ -0,0 +1,17 @@ +; Check for state persistence bugs in the RISC-V MC backend +; This should neither fail (in the comparison that the second object +; is bit-identical to the first) nor crash. Either failure would most +; likely indicate some state that is not properly reset in the +; appropriate ::reset method. +; RUN: llc -compile-twice -filetype=obj -mtriple=riscv64 %s -o - \ +; RUN: | llvm-objdump --section-headers - \ +; RUN: | FileCheck %s + +; CHECK: Sections: +; CHECK-NEXT: Idx Name Size VMA Type +; CHECK-NEXT: 0 +; CHECK-NEXT: 1 .strtab +; CHECK-NEXT: 2 .text +; CHECK-NEXT: 3 .note.GNU-stack +; CHECK-NEXT: 4 .riscv.attributes +; CHECK-NEXT: 5 .symtab