Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -82,7 +82,12 @@ virtual void emitLabel(MCSymbol *Symbol); // Allow a target to add behavior to the emitAssignment of MCStreamer. virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value); - + // Allow a target to add behavior to the emitInstruction of MCStreamer. + virtual void emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI); + // Allow a target to add behavior to the SwitchSection of MCStreamer. + virtual void SwitchSection(const MCSection *Section, + const MCExpr *Subsection = nullptr); virtual void finish(); }; @@ -343,6 +348,9 @@ SectionStack.back().first = MCSectionSubPair(Section, Subsection); ChangeSection(Section, Subsection); } + MCTargetStreamer *TS = getTargetStreamer(); + if (TS) + TS->SwitchSection(Section, Subsection); } /// SwitchSectionNoChange - Set the current section where code is being @@ -706,7 +714,7 @@ /// EmitInstruction - Emit the given @p Instruction into the current /// section. - virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) = 0; + virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// \brief Set the bundle alignment mode from now on in the section. /// The argument is the power of 2 to which the alignment is set. The Index: lib/MC/MCObjectStreamer.cpp =================================================================== --- lib/MC/MCObjectStreamer.cpp +++ lib/MC/MCObjectStreamer.cpp @@ -190,6 +190,7 @@ } void MCObjectStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { + MCStreamer::EmitInstruction(Inst, STI); // Scan for values. for (unsigned i = Inst.getNumOperands(); i--; ) if (Inst.getOperand(i).isExpr()) Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -36,6 +36,12 @@ void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} +void MCTargetStreamer::emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) {} + +void MCTargetStreamer::SwitchSection(const MCSection *Section, + const MCExpr *Subsection) {} + MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false), CurrentW64UnwindInfo(nullptr), LastSymbol(nullptr) { @@ -651,3 +657,11 @@ if (TS) TS->emitAssignment(Symbol, Value); } + +void MCStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCTargetStreamer *TS = getTargetStreamer(); + if (TS) + TS->emitInstruction(Inst, STI); +} + Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2439,7 +2439,7 @@ if (getParser().parseExpression(Value)) return true; - getParser().getStreamer().EmitValue(Value, Size); + getTargetStreamer().emitDirectiveData(Value, Size); if (getLexer().is(AsmToken::EndOfStatement)) break; Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -32,6 +32,10 @@ MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} +MCELFStreamer &MipsTargetStreamer::getStreamer() { + return static_cast(Streamer); +} + MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) : MipsTargetStreamer(S), OS(OS) {} @@ -167,6 +171,11 @@ OS << Sym.getName() << "\n"; } +void MipsTargetAsmStreamer::emitDirectiveData(const MCExpr *Value, + unsigned Size) { + getStreamer().EmitValue(Value, Size); +} + // This part is for ELF object output. MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) @@ -218,19 +227,29 @@ } void MipsTargetELFStreamer::emitLabel(MCSymbol *Symbol) { - if (!isMicroMipsEnabled()) - return; - MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Symbol); - uint8_t Type = MCELF::GetType(Data); - if (Type != ELF::STT_FUNC) - return; + Labels.push_back(Symbol); +} - // The "other" values are stored in the last 6 bits of the second byte - // The traditional defines for STO values assume the full byte and thus - // the shift to pack it. - MCELF::setOther(Data, ELF::STO_MIPS_MICROMIPS >> 2); +void MipsTargetELFStreamer::emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + if (isMicroMipsEnabled()) + for (unsigned j = 0, e = Labels.size(); j != e; ++j) { + MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Labels[j]); + uint8_t Type = MCELF::GetType(Data); + // The "other" values are stored in the last 6 bits of the second byte + // The traditional defines for STO values assume the full byte and thus + // the shift to pack it. + MCELF::setOther(Data, ELF::STO_MIPS_MICROMIPS >> 2); + } + Labels.clear(); } +void MipsTargetELFStreamer::SwitchSection(const MCSection *Section, + const MCExpr *Subsection) { + Labels.clear(); +} + + void MipsTargetELFStreamer::finish() { MCAssembler &MCA = getStreamer().getAssembler(); MCContext &Context = MCA.getContext(); @@ -290,10 +309,6 @@ MCELF::setOther(SymbolData, ELF::STO_MIPS_MICROMIPS >> 2); } -MCELFStreamer &MipsTargetELFStreamer::getStreamer() { - return static_cast(Streamer); -} - void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { MicroMipsEnabled = true; @@ -529,3 +544,10 @@ Inst.addOperand(MCOperand::CreateReg(RegNo)); getStreamer().EmitInstruction(Inst, STI); } + +void MipsTargetELFStreamer::emitDirectiveData(const MCExpr *Value, + unsigned Size) { + getStreamer().EmitValue(Value, Size); + Labels.clear(); +} + Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -19,6 +19,7 @@ public: MipsTargetStreamer(MCStreamer &S); + MCELFStreamer &getStreamer(); virtual void emitDirectiveSetMicroMips() = 0; virtual void emitDirectiveSetNoMicroMips() = 0; virtual void emitDirectiveSetMips16() = 0; @@ -52,6 +53,8 @@ virtual void emitDirectiveCpload(unsigned RegNo) = 0; virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) = 0; + + virtual void emitDirectiveData(const MCExpr *Value, unsigned Size) = 0; }; // This part is for ascii assembly output @@ -93,6 +96,8 @@ virtual void emitDirectiveCpload(unsigned RegNo); void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; + + void emitDirectiveData(const MCExpr *Value, unsigned Size) override; }; // This part is for ELF object output @@ -100,14 +105,18 @@ bool MicroMipsEnabled; const MCSubtargetInfo &STI; bool Pic; + SmallVector Labels; public: bool isMicroMipsEnabled() const { return MicroMipsEnabled; } - MCELFStreamer &getStreamer(); MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); void emitLabel(MCSymbol *Symbol) override; void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + void emitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) override; + void SwitchSection(const MCSection *Section, + const MCExpr *Subsection = nullptr) override; void finish() override; void emitDirectiveSetMicroMips() override; @@ -144,6 +153,8 @@ void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; + void emitDirectiveData(const MCExpr *Value, unsigned Size) override; + protected: bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; } bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; } Index: test/MC/Mips/micromips-label-test-sections.s =================================================================== --- test/MC/Mips/micromips-label-test-sections.s +++ test/MC/Mips/micromips-label-test-sections.s @@ -0,0 +1,33 @@ +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 \ +# RUN: -mattr=+micromips -filetype=obj -o - | llvm-readobj -t | FileCheck %s + .text + .set micromips +f: + nop +g: + .section .text +h: + nop +# CHECK: Symbols [ +# CHECK: Symbol { +# CHECK: Name: f +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 128 +# CHECK: Section: .text +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: g +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 0 +# CHECK: Section: .text +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: h +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 128 +# CHECK: Section: .text +# CHECK: } +# CHECK: ] Index: test/MC/Mips/micromips-label-test.s =================================================================== --- test/MC/Mips/micromips-label-test.s +++ test/MC/Mips/micromips-label-test.s @@ -0,0 +1,53 @@ +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 \ +# RUN: -mattr=+micromips -filetype=obj -o - | llvm-readobj -t | FileCheck %s + .text + .set nomicromips +f: + nop +g: + .set micromips + nop +h: + .word 0 +i: + nop +j: + .set nomicromips + nop +# CHECK: Symbols [ +# CHECK: Symbol { +# CHECK: Name: f +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 0 +# CHECK: Section: .text +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: g +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 128 +# CHECK: Section: .text +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: h +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 0 +# CHECK: Section: .text +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: i +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 128 +# CHECK: Section: .text +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: j +# CHECK: Binding: Local +# CHECK: Type: None +# CHECK: Other: 0 +# CHECK: Section: .text +# CHECK: } +# CHECK: ]