Index: include/llvm/MC/MCELFStreamer.h =================================================================== --- include/llvm/MC/MCELFStreamer.h +++ include/llvm/MC/MCELFStreamer.h @@ -41,6 +41,8 @@ void InitSections(bool NoExecStack) override; void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void EmitLabelEx(MCSymbol *Symbol, SMLoc Loc = SMLoc(), + const MCSubtargetInfo *STI = nullptr) override; void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; Index: include/llvm/MC/MCObjectStreamer.h =================================================================== --- include/llvm/MC/MCObjectStreamer.h +++ include/llvm/MC/MCObjectStreamer.h @@ -107,6 +107,8 @@ /// @{ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void EmitLabelEx(MCSymbol *Symbol, SMLoc Loc = SMLoc(), + const MCSubtargetInfo *STI = nullptr) override; virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F); void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -438,6 +438,11 @@ // add the section we're emitting it to later. virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()); + /// Similar to EmitLabel but uses subtarget info to check if symbol + /// can be emitted in the current fragment. + virtual void EmitLabelEx(MCSymbol *Symbol, SMLoc Loc = SMLoc(), + const MCSubtargetInfo *STI = nullptr); + virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); /// Note in the output the specified \p Flag. Index: lib/MC/MCELFStreamer.cpp =================================================================== --- lib/MC/MCELFStreamer.cpp +++ lib/MC/MCELFStreamer.cpp @@ -97,8 +97,13 @@ } void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { + return EmitLabelEx(S, Loc); +} + +void MCELFStreamer::EmitLabelEx(MCSymbol *S, SMLoc Loc, + const MCSubtargetInfo *STI) { auto *Symbol = cast(S); - MCObjectStreamer::EmitLabel(Symbol, Loc); + MCObjectStreamer::EmitLabelEx(Symbol, Loc, STI); const MCSectionELF &Section = static_cast(*getCurrentSectionOnly()); Index: lib/MC/MCObjectStreamer.cpp =================================================================== --- lib/MC/MCObjectStreamer.cpp +++ lib/MC/MCObjectStreamer.cpp @@ -230,6 +230,11 @@ } void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { + return EmitLabelEx(Symbol, Loc); +} + +void MCObjectStreamer::EmitLabelEx(MCSymbol *Symbol, SMLoc Loc, + const MCSubtargetInfo *STI) { MCStreamer::EmitLabel(Symbol, Loc); getAssembler().registerSymbol(*Symbol); @@ -238,8 +243,7 @@ // Otherwise queue the label and set its fragment pointer when we emit the // next fragment. auto *F = dyn_cast_or_null(getCurrentFragment()); - if (F && !(getAssembler().isBundlingEnabled() && - getAssembler().getRelaxAll())) { + if (F && CanReuseDataFragment(*F, getAssembler(), STI)) { Symbol->setFragment(F); Symbol->setOffset(F->getContents().size()); } else { Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -1824,7 +1824,7 @@ // Emit the label. if (!getTargetParser().isParsingInlineAsm()) - Out.EmitLabel(Sym, IDLoc); + Out.EmitLabelEx(Sym, IDLoc, &getTargetParser().getSTI()); // If we are generating dwarf for assembly source files then gather the // info to make a dwarf label entry for this label if needed. Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -343,6 +343,11 @@ SymbolOrdering[Symbol] = 1 + SymbolOrdering.size(); } +void MCStreamer::EmitLabelEx(MCSymbol *Symbol, SMLoc Loc, + const MCSubtargetInfo *STI) { + // Default implementation does not use STI. + return EmitLabel(Symbol, Loc); +} void MCStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) { Symbol->redefineIfPossible(); Index: lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -1446,7 +1446,7 @@ MCSymbol *TmpLabel = Ctx.createTempSymbol( "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false); - Out.EmitLabel(TmpLabel); + Out.EmitLabelEx(TmpLabel, IDLoc, &getSTI()); const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx); emitToStreamer( Index: test/MC/RISCV/option-mix.s =================================================================== --- /dev/null +++ test/MC/RISCV/option-mix.s @@ -0,0 +1,51 @@ +# RUN: llvm-mc %s -triple=riscv32 | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc %s -triple=riscv64 | FileCheck -check-prefix=ASM %s +# RUN: llvm-mc -filetype=obj -triple riscv32 < %s \ +# RUN: | llvm-objdump -d -riscv-no-aliases - | FileCheck -check-prefix=DISASM %s +# RUN: llvm-mc -filetype=obj -triple riscv64 < %s \ +# RUN: | llvm-objdump -d -riscv-no-aliases - | FileCheck -check-prefix=DISASM %s + +# Checks change of options does not cause error: could not find corresponding %pcrel_hi +# when assembling pseudoinstruction and its extended form. + +.option push +.option norelax + la a0, a_symbol +.option pop + la a1, another_symbol + +# ASM: .Lpcrel_hi0: +# ASM: auipc a0, %pcrel_hi(a_symbol) +# ASM: addi a0, a0, %pcrel_lo(.Lpcrel_hi0) +# ASM: .Lpcrel_hi1: +# ASM: auipc a1, %pcrel_hi(another_symbol) +# ASM: addi a1, a1, %pcrel_lo(.Lpcrel_hi1) + +# DISASM: .Lpcrel_hi0: +# DISASM: auipc a0, 0 +# DISASM: addi a0, a0, 0 +# DISASM:.Lpcrel_hi1: +# DISASM: auipc a1, 0 +# DISASM: addi a1, a1, 0 + +.option push +.option norelax +1:auipc a0, %pcrel_hi(a_symbol) + addi a0, a0, %pcrel_lo(1b) +.option pop +2:auipc a1, %pcrel_hi(another_symbol) + addi a1, a1, %pcrel_lo(2b) + +# ASM: .Ltmp0: +# ASM: auipc a0, %pcrel_hi(a_symbol) +# ASM: addi a0, a0, %pcrel_lo(.Ltmp0) +# ASM: .Ltmp1: +# ASM: auipc a1, %pcrel_hi(another_symbol) +# ASM: addi a1, a1, %pcrel_lo(.Ltmp1) + +# DISASM: .Ltmp0: +# DISASM: auipc a0, 0 +# DISASM: addi a0, a0, 0 +# DISASM: .Ltmp1: +# DISASM: auipc a1, 0 +# DISASM: addi a1, a1, 0