Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -210,6 +210,7 @@ bool parseDirectiveNaN(); bool parseDirectiveSet(); bool parseDirectiveOption(); + bool parseInsnDirective(); bool parseSetAtDirective(); bool parseSetNoAtDirective(); @@ -4039,6 +4040,22 @@ return false; } +/// parseInsnDirective +/// ::= .insn +bool MipsAsmParser::parseInsnDirective() { + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + // The actual label marking happens in MipsELFStreamer::markLabelsAsMicroMips. + getTargetStreamer().emitDirectiveInsn(); + + getParser().Lex(); // Eat EndOfStatement token. + return false; +} + /// parseDirectiveModule /// ::= .module oddspreg /// ::= .module nooddspreg @@ -4429,6 +4446,9 @@ if (IDVal == ".module") return parseDirectiveModule(); + if (IDVal == ".insn") + return parseInsnDirective(); + return true; } Index: lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -65,6 +65,9 @@ /// Emits all the option records stored up until the point it's called. void EmitMipsOptionRecords(); + + /// Mark labels as microMIPS. + void markLabelsAsMicroMips(); }; MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, Index: lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -34,16 +34,20 @@ RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo); } - if (ELFTargetStreamer->isMicroMipsEnabled()) { - for (auto Label : Labels) { - MCSymbolData &Data = getOrCreateSymbolData(Label); - // 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); - } - } + if (ELFTargetStreamer->isMicroMipsEnabled()) + markLabelsAsMicroMips(); + else + Labels.clear(); +} +void MipsELFStreamer::markLabelsAsMicroMips() { + for (auto Label : Labels) { + MCSymbolData &Data = getOrCreateSymbolData(Label); + // 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(); } Index: lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -54,6 +54,7 @@ void MipsTargetStreamer::emitDirectiveNaNLegacy() {} void MipsTargetStreamer::emitDirectiveOptionPic0() {} void MipsTargetStreamer::emitDirectiveOptionPic2() {} +void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); } void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) {} void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} @@ -185,6 +186,11 @@ OS << "\t.option\tpic2\n"; } +void MipsTargetAsmStreamer::emitDirectiveInsn() { + MipsTargetStreamer::emitDirectiveInsn(); + OS << "\t.insn\n"; +} + void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) { OS << "\t.frame\t$" @@ -629,6 +635,15 @@ MCA.setELFHeaderEFlags(Flags); } +void MipsTargetELFStreamer::emitDirectiveInsn() { + MipsTargetStreamer::emitDirectiveInsn(); + // FIXME: Also mark labels when in MIPS16 mode. + if (isMicroMipsEnabled()) { + MipsELFStreamer &MEF = static_cast(Streamer); + MEF.markLabelsAsMicroMips(); + } +} + void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg_) { MCContext &Context = getStreamer().getAssembler().getContext(); Index: lib/Target/Mips/MipsTargetStreamer.h =================================================================== --- lib/Target/Mips/MipsTargetStreamer.h +++ lib/Target/Mips/MipsTargetStreamer.h @@ -45,6 +45,7 @@ virtual void emitDirectiveNaNLegacy(); virtual void emitDirectiveOptionPic0(); virtual void emitDirectiveOptionPic2(); + virtual void emitDirectiveInsn(); virtual void emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg); virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff); @@ -160,6 +161,7 @@ void emitDirectiveNaNLegacy() override; void emitDirectiveOptionPic0() override; void emitDirectiveOptionPic2() override; + void emitDirectiveInsn() override; void emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) override; void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; @@ -228,6 +230,7 @@ void emitDirectiveNaNLegacy() override; void emitDirectiveOptionPic0() override; void emitDirectiveOptionPic2() override; + void emitDirectiveInsn() override; void emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) override; void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; Index: test/MC/Mips/insn-directive.s =================================================================== --- /dev/null +++ test/MC/Mips/insn-directive.s @@ -0,0 +1,84 @@ +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 | FileCheck %s --check-prefix=ASM + +# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -filetype=obj -o - | \ +# RUN: llvm-readobj -symbols - | FileCheck %s --check-prefix=OBJ + + .set micromips + + .global f_mm_insn_data + .type f_mm_insn_data, @function +f_mm_insn_data: + .insn + .word 0x00e73910 # add $7, $7, $7 + + .global f_mm_insn_instr + .type f_mm_insn_instr, @function +f_mm_insn_instr: + .insn + add $7, $7, $7 + + .global o_mm_insn_data + .type o_mm_insn_data, @object +o_mm_insn_data: + .insn + .word 0x00e73910 # add $7, $7, $7 + + .global o_mm_insn_instr + .type o_mm_insn_instr, @object +o_mm_insn_instr: + .insn + add $7, $7, $7 + + .set nomicromips + + .global f_normal_insn_data + .type f_normal_insn_data, @function +f_normal_insn_data: + .insn + .word 0x00e73820 # add $7, $7, $7 + + .global f_normal_insn_instr + .type f_normal_insn_instr, @function +f_normal_insn_instr: + .insn + add $7, $7, $7 + + .global o_normal_insn_data + .type o_normal_insn_data, @object +o_normal_insn_data: + .insn + .word 0x00e73820 # add $7, $7, $7 + + .global o_normal_insn_instr + .type o_normal_insn_instr, @object +o_normal_insn_instr: + .insn + add $7, $7, $7 + +# ASM: .insn + +# OBJ: Symbols [ +# OBJ: Name: f_mm_insn_data +# OBJ: Other: 128 + +# OBJ: Name: f_mm_insn_instr +# OBJ: Other: 128 + +# OBJ: Name: f_normal_insn_data +# OBJ: Other: 0 + +# OBJ: Name: f_normal_insn_instr +# OBJ: Other: 0 + +# OBJ: Name: o_mm_insn_data +# OBJ: Other: 128 + +# OBJ: Name: o_mm_insn_instr +# OBJ: Other: 128 + +# OBJ: Name: o_normal_insn_data +# OBJ: Other: 0 + +# OBJ: Name: o_normal_insn_instr +# OBJ: Other: 0 +# OBJ: ]