Skip to content

release/18.x: [Mips] Fix unable to handle inline assembly ends with compat-branch o… (#77291) #82870

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions lld/test/ELF/mips-pc-relocs.s
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ __start:
# ^-- (0x20020-0x20000)>>2
# CHECK-NEXT: 20004: beqc $5, $6, 0x20020
# ^-- (0x20020-4-0x20004)>>2
# CHECK-NEXT: 20008: beqzc $9, 0x20020
# ^-- (0x20020-4-0x20008)>>2
# CHECK-NEXT: 2000c: bc 0x20020
# ^-- (0x20020-4-0x2000c)>>2
# CHECK-NEXT: 20010: aluipc $2, 0
# ^-- %hi(0x20020-0x20010)
# CHECK-NEXT: 20014: addiu $2, $2, 12
# ^-- %lo(0x20020-0x20014)
# CHECK-NEXT: 20008: nop
# CHECK-NEXT: 2000c: beqzc $9, 0x20020
# ^-- (0x20020-4-0x2000c)>>2
# CHECK-NEXT: 20010: nop
# CHECK-NEXT: 20014: bc 0x20020
# ^-- (0x20020-4-0x200014)>>2
# CHECK-NEXT: 20018: aluipc $2, 0
# ^-- %hi(0x20020-0x20018)
# CHECK-NEXT: 2001c: addiu $2, $2, 4
# ^-- %lo(0x20020-0x2001c)
78 changes: 77 additions & 1 deletion llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool IsLittleEndian;
bool IsPicEnabled;
bool IsCpRestoreSet;
bool CurForbiddenSlotAttr;
int CpRestoreOffset;
unsigned GPReg;
unsigned CpSaveLocation;
Expand Down Expand Up @@ -552,6 +553,7 @@ class MipsAsmParser : public MCTargetAsmParser {

CurrentFn = nullptr;

CurForbiddenSlotAttr = false;
IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();

IsCpRestoreSet = false;
Expand Down Expand Up @@ -723,6 +725,16 @@ class MipsAsmParser : public MCTargetAsmParser {
return getSTI().hasFeature(Mips::FeatureGINV);
}

bool hasForbiddenSlot(const MCInstrDesc &MCID) const {
return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);
}

bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {
return !(MCID.TSFlags & MipsII::IsCTI);
}

void onEndOfFile() override;

/// Warn if RegIndex is the same as the current AT.
void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);

Expand Down Expand Up @@ -2307,7 +2319,41 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,

bool FillDelaySlot =
MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
if (FillDelaySlot)

// Get previous instruction`s forbidden slot attribute and
// whether set reorder.
bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;

// Flag represents we set reorder after nop.
bool SetReorderAfterNop = false;

// If previous instruction has forbidden slot and .set reorder
// is active and current instruction is CTI.
// Then emit a NOP after it.
if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {
TOut.emitEmptyDelaySlot(false, IDLoc, STI);
// When 'FillDelaySlot' is true, the existing logic will add
// noreorder before instruction and reorder after it. So there
// need exclude this case avoiding two '.set reorder'.
// The format of the first case is:
// .set noreorder
// bnezc
// nop
// .set reorder
if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
SetReorderAfterNop = true;
TOut.emitDirectiveSetReorder();
}
}

// Save current instruction`s forbidden slot and whether set reorder.
// This is the judgment condition for whether to add nop.
// We would add a couple of '.set noreorder' and '.set reorder' to
// wrap the current instruction and the next instruction.
CurForbiddenSlotAttr =
hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();

if (FillDelaySlot || CurForbiddenSlotAttr)
TOut.emitDirectiveSetNoReorder();

MacroExpanderResultTy ExpandResult =
Expand All @@ -2322,6 +2368,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return true;
}

// When current instruction was not CTI, recover reorder state.
// The format of the second case is:
// .set noreoder
// bnezc
// add
// .set reorder
if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
AssemblerOptions.back()->isReorder()) {
TOut.emitDirectiveSetReorder();
}

// We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
// If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
if (inMicroMipsMode()) {
Expand All @@ -2331,6 +2388,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,

// If this instruction has a delay slot and .set reorder is active,
// emit a NOP after it.
// The format of the third case is:
// .set noreorder
// bnezc
// nop
// .set noreorder
// j
// nop
// .set reorder
if (FillDelaySlot) {
TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
TOut.emitDirectiveSetReorder();
Expand All @@ -2356,6 +2421,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return false;
}

void MipsAsmParser::onEndOfFile() {
MipsTargetStreamer &TOut = getTargetStreamer();
SMLoc IDLoc = SMLoc();
// If has pending forbidden slot, fill nop and recover reorder.
if (CurForbiddenSlotAttr) {
TOut.emitEmptyDelaySlot(false, IDLoc, STI);
if (AssemblerOptions.back()->isReorder())
TOut.emitDirectiveSetReorder();
}
}

MipsAsmParser::MacroExpanderResultTy
MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI) {
Expand Down
71 changes: 71 additions & 0 deletions llvm/test/CodeGen/Mips/llvm-ir/forbidden-slot-ir.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
target triple = "mipsisa32r6el-unknown-linux-gnu"

; RUN: llc -filetype=asm %s -o - | FileCheck %s --check-prefix=MIPSELR6
; Function Attrs: noinline nounwind optnone uwtable
define i1 @foo0() nounwind {
; MIPSELR6: bnezc $1, $BB0_2
; MIPSELR6-NEXT: nop
; MIPSELR6: jr $ra
entry:
%0 = icmp eq i32 0, 1
br i1 %0, label %2, label %3
ret i1 %0
2:
ret i1 %0
3:
ret i1 %0
}

define i32 @foo1() nounwind {
; MIPSELR6: addiu $2, $2, 1
; MIPSELR6-NEXT: .set noreorder
; MIPSELR6-NEXT: beqzc $2, $tmp0
; MIPSELR6-NEXT: nop
; MIPSELR6-NEXT: .set reorder
; MIPSELR6: jrc $ra
entry:
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b", "=r"() nounwind
ret i32 %0
}

define i32 @foo2() nounwind {
; MIPSELR6: .set push
; MIPSELR6-NEXT: .set at
; MIPSELR6-NEXT: .set macro
; MIPSELR6-NEXT: .set reorder
; MIPSELR6: .set noreorder
; MIPSELR6-NEXT: beqzc $9, End
; MIPSELR6-NEXT: nop
; MIPSELR6-NEXT: .set reorder
; MIPSELR6: addiu $9, $9, 1
entry:
%0 = tail call i32 asm "beqzc $$t1, End", "=r"() nounwind
%1 = tail call i32 asm "addiu $$t1, $$t1, 1", "=r"() nounwind
%2 = add nsw i32 %1, %0
ret i32 %2
}

define i32 @foo3() nounwind {
; MIPSELR6: addiu $2, $2, 1
; MIPSELR6-NEXT: .set noreorder
; MIPSELR6-NEXT: beqzc $2, $tmp1
; MIPSELR6-NEXT: nop
; MIPSELR6-NEXT: .set noreorder
; MIPSELR6-NEXT: j End
; MIPSELR6-NEXT: nop
; MIPSELR6-NEXT: .set reorder
entry:
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; j End", "=r"() nounwind
ret i32 %0
}

define i32 @foo4() nounwind {
; MIPSELR6: addiu $2, $2, 1
; MIPSELR6-NEXT: .set noreorder
; MIPSELR6-NEXT: beqzc $2, $tmp2
; MIPSELR6-NEXT: addiu $2, $2, 1
; MIPSELR6-NEXT: .set reorder
entry:
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; addiu $0, $0, 1", "=r"() nounwind
ret i32 %0
}
18 changes: 18 additions & 0 deletions llvm/test/MC/Mips/forbidden-slot.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# RUN: llvm-mc -assemble -mcpu=mips64r6 -arch=mips64el -filetype=obj %s -o tmp.o
# RUN: llvm-objdump -d tmp.o | FileCheck %s --check-prefix=MIPSELR6

# MIPSELR6: 0000000000000000 <aaa>:
# MIPSELR6-NEXT: beqzc $13, 0x0 <aaa>
# MIPSELR6-NEXT: b 0x0 <aaa>
# MIPSELR6: 0000000000000008 <bbb>:
# MIPSELR6-NEXT: beqzc $13, 0x8 <bbb>
# MIPSELR6-NEXT: nop <aaa>
# MIPSELR6: b 0x8 <bbb>
.set noreorder
aaa:
beqzc $t1, aaa
b aaa
.set reorder
bbb:
beqzc $t1, bbb
b bbb
22 changes: 11 additions & 11 deletions llvm/test/MC/Mips/mips32r6/relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,17 @@
# CHECK-ELF: Relocations [
# CHECK-ELF: 0x0 R_MIPS_PC19_S2 bar
# CHECK-ELF: 0x4 R_MIPS_PC16 bar
# CHECK-ELF: 0x8 R_MIPS_PC16 bar
# CHECK-ELF: 0xC R_MIPS_PC21_S2 bar
# CHECK-ELF: 0x10 R_MIPS_PC21_S2 bar
# CHECK-ELF: 0x14 R_MIPS_PC26_S2 bar
# CHECK-ELF: 0x18 R_MIPS_PC26_S2 bar
# CHECK-ELF: 0x1C R_MIPS_PCHI16 bar
# CHECK-ELF: 0x20 R_MIPS_PCLO16 bar
# CHECK-ELF: 0x24 R_MIPS_PC19_S2 bar
# CHECK-ELF: 0x28 R_MIPS_PC19_S2 bar
# CHECK-ELF: 0x2C R_MIPS_LO16 bar
# CHECK-ELF: 0x30 R_MIPS_LO16 bar
# CHECK-ELF: 0xC R_MIPS_PC16 bar
# CHECK-ELF: 0x14 R_MIPS_PC21_S2 bar
# CHECK-ELF: 0x1C R_MIPS_PC21_S2 bar
# CHECK-ELF: 0x24 R_MIPS_PC26_S2 bar
# CHECK-ELF: 0x28 R_MIPS_PC26_S2 bar
# CHECK-ELF: 0x2C R_MIPS_PCHI16 bar
# CHECK-ELF: 0x30 R_MIPS_PCLO16 bar
# CHECK-ELF: 0x34 R_MIPS_PC19_S2 bar
# CHECK-ELF: 0x38 R_MIPS_PC19_S2 bar
# CHECK-ELF: 0x3C R_MIPS_LO16 bar
# CHECK-ELF: 0x40 R_MIPS_LO16 bar
# CHECK-ELF: ]

addiupc $2,bar
Expand Down
26 changes: 13 additions & 13 deletions llvm/test/MC/Mips/mips64r6/relocations.s
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,19 @@
# CHECK-ELF: Relocations [
# CHECK-ELF: 0x0 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x4 R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x8 R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0xC R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x10 R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x14 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x18 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x1C R_MIPS_PCHI16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x20 R_MIPS_PCLO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x24 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x28 R_MIPS_PC18_S3/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x2C R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x30 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x34 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x38 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0xC R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x14 R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x1C R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x24 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x28 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
# CHECK-ELF: 0x2C R_MIPS_PCHI16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x30 R_MIPS_PCLO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x34 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x38 R_MIPS_PC18_S3/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x3C R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x40 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x44 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: 0x48 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
# CHECK-ELF: ]

addiupc $2,bar
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/Mips/relocation.s
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ baz: .long foo // RELOC: R_MIPS_32 foo
// ENCLE: addiu $2, $3, %tprel_lo(foo) # encoding: [A,A,0x62,0x24]
// FIXUP: # fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_Mips_TPREL_LO

// DATA-NEXT: 00C0: D85FFFFF CBFFFFFF EC580000 EC480000
// DATA-NEXT: 00C0: D85FFFFF 00000000 CBFFFFFF EC580000
// ?????: R_MIPS_GLOB_DAT foo
.set mips32r6
beqzc $2, foo // RELOC: R_MIPS_PC21_S2 foo
Expand All @@ -262,7 +262,7 @@ baz: .long foo // RELOC: R_MIPS_32 foo
// ENCLE: lwpc $2, foo # encoding: [A,A,0b01001AAA,0xec]
// FIXUP: # fixup A - offset: 0, value: foo, kind: fixup_MIPS_PC19_S2

// DATA-NEXT: 00D0: 24620000 24620000 00000000
// DATA-NEXT: 00D0: EC480000 24620000 24620000 00000000
addiu $2, $3, %pcrel_hi(foo) // RELOC: R_MIPS_PCHI16 foo
// ENCBE: addiu $2, $3, %pcrel_hi(foo) # encoding: [0x24,0x62,A,A]
// ENCLE: addiu $2, $3, %pcrel_hi(foo) # encoding: [A,A,0x62,0x24]
Expand Down