Skip to content

Commit e2182a6

Browse files
yingopqtstellar
authored andcommitted
[Mips] Fix unable to handle inline assembly ends with compat-branch o… (#77291)
…n MIPS Modify: Add a global variable 'CurForbiddenSlotAttr' to 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. Then we can get previous instruction`s forbidden slot attribute and whether set reorder by 'CurForbiddenSlotAttr'. If previous instruction has forbidden slot and .set reorder is active and current instruction is CTI. Then emit a NOP after it. Fix #61045. Because https://reviews.llvm.org/D158589 was 'Needs Review' state, not ending, so we commit pull request again. (cherry picked from commit 96abee5)
1 parent 6d8f929 commit e2182a6

File tree

7 files changed

+202
-35
lines changed

7 files changed

+202
-35
lines changed

Diff for: lld/test/ELF/mips-pc-relocs.s

+10-8
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ __start:
4040
# ^-- (0x20020-0x20000)>>2
4141
# CHECK-NEXT: 20004: beqc $5, $6, 0x20020
4242
# ^-- (0x20020-4-0x20004)>>2
43-
# CHECK-NEXT: 20008: beqzc $9, 0x20020
44-
# ^-- (0x20020-4-0x20008)>>2
45-
# CHECK-NEXT: 2000c: bc 0x20020
46-
# ^-- (0x20020-4-0x2000c)>>2
47-
# CHECK-NEXT: 20010: aluipc $2, 0
48-
# ^-- %hi(0x20020-0x20010)
49-
# CHECK-NEXT: 20014: addiu $2, $2, 12
50-
# ^-- %lo(0x20020-0x20014)
43+
# CHECK-NEXT: 20008: nop
44+
# CHECK-NEXT: 2000c: beqzc $9, 0x20020
45+
# ^-- (0x20020-4-0x2000c)>>2
46+
# CHECK-NEXT: 20010: nop
47+
# CHECK-NEXT: 20014: bc 0x20020
48+
# ^-- (0x20020-4-0x200014)>>2
49+
# CHECK-NEXT: 20018: aluipc $2, 0
50+
# ^-- %hi(0x20020-0x20018)
51+
# CHECK-NEXT: 2001c: addiu $2, $2, 4
52+
# ^-- %lo(0x20020-0x2001c)

Diff for: llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

+77-1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class MipsAsmParser : public MCTargetAsmParser {
150150
bool IsLittleEndian;
151151
bool IsPicEnabled;
152152
bool IsCpRestoreSet;
153+
bool CurForbiddenSlotAttr;
153154
int CpRestoreOffset;
154155
unsigned GPReg;
155156
unsigned CpSaveLocation;
@@ -552,6 +553,7 @@ class MipsAsmParser : public MCTargetAsmParser {
552553

553554
CurrentFn = nullptr;
554555

556+
CurForbiddenSlotAttr = false;
555557
IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
556558

557559
IsCpRestoreSet = false;
@@ -723,6 +725,16 @@ class MipsAsmParser : public MCTargetAsmParser {
723725
return getSTI().hasFeature(Mips::FeatureGINV);
724726
}
725727

728+
bool hasForbiddenSlot(const MCInstrDesc &MCID) const {
729+
return !inMicroMipsMode() && (MCID.TSFlags & MipsII::HasForbiddenSlot);
730+
}
731+
732+
bool SafeInForbiddenSlot(const MCInstrDesc &MCID) const {
733+
return !(MCID.TSFlags & MipsII::IsCTI);
734+
}
735+
736+
void onEndOfFile() override;
737+
726738
/// Warn if RegIndex is the same as the current AT.
727739
void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
728740

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

23082320
bool FillDelaySlot =
23092321
MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
2310-
if (FillDelaySlot)
2322+
2323+
// Get previous instruction`s forbidden slot attribute and
2324+
// whether set reorder.
2325+
bool PrevForbiddenSlotAttr = CurForbiddenSlotAttr;
2326+
2327+
// Flag represents we set reorder after nop.
2328+
bool SetReorderAfterNop = false;
2329+
2330+
// If previous instruction has forbidden slot and .set reorder
2331+
// is active and current instruction is CTI.
2332+
// Then emit a NOP after it.
2333+
if (PrevForbiddenSlotAttr && !SafeInForbiddenSlot(MCID)) {
2334+
TOut.emitEmptyDelaySlot(false, IDLoc, STI);
2335+
// When 'FillDelaySlot' is true, the existing logic will add
2336+
// noreorder before instruction and reorder after it. So there
2337+
// need exclude this case avoiding two '.set reorder'.
2338+
// The format of the first case is:
2339+
// .set noreorder
2340+
// bnezc
2341+
// nop
2342+
// .set reorder
2343+
if (AssemblerOptions.back()->isReorder() && !FillDelaySlot) {
2344+
SetReorderAfterNop = true;
2345+
TOut.emitDirectiveSetReorder();
2346+
}
2347+
}
2348+
2349+
// Save current instruction`s forbidden slot and whether set reorder.
2350+
// This is the judgment condition for whether to add nop.
2351+
// We would add a couple of '.set noreorder' and '.set reorder' to
2352+
// wrap the current instruction and the next instruction.
2353+
CurForbiddenSlotAttr =
2354+
hasForbiddenSlot(MCID) && AssemblerOptions.back()->isReorder();
2355+
2356+
if (FillDelaySlot || CurForbiddenSlotAttr)
23112357
TOut.emitDirectiveSetNoReorder();
23122358

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

2371+
// When current instruction was not CTI, recover reorder state.
2372+
// The format of the second case is:
2373+
// .set noreoder
2374+
// bnezc
2375+
// add
2376+
// .set reorder
2377+
if (PrevForbiddenSlotAttr && !SetReorderAfterNop && !FillDelaySlot &&
2378+
AssemblerOptions.back()->isReorder()) {
2379+
TOut.emitDirectiveSetReorder();
2380+
}
2381+
23252382
// We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
23262383
// If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
23272384
if (inMicroMipsMode()) {
@@ -2331,6 +2388,14 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23312388

23322389
// If this instruction has a delay slot and .set reorder is active,
23332390
// emit a NOP after it.
2391+
// The format of the third case is:
2392+
// .set noreorder
2393+
// bnezc
2394+
// nop
2395+
// .set noreorder
2396+
// j
2397+
// nop
2398+
// .set reorder
23342399
if (FillDelaySlot) {
23352400
TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
23362401
TOut.emitDirectiveSetReorder();
@@ -2356,6 +2421,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23562421
return false;
23572422
}
23582423

2424+
void MipsAsmParser::onEndOfFile() {
2425+
MipsTargetStreamer &TOut = getTargetStreamer();
2426+
SMLoc IDLoc = SMLoc();
2427+
// If has pending forbidden slot, fill nop and recover reorder.
2428+
if (CurForbiddenSlotAttr) {
2429+
TOut.emitEmptyDelaySlot(false, IDLoc, STI);
2430+
if (AssemblerOptions.back()->isReorder())
2431+
TOut.emitDirectiveSetReorder();
2432+
}
2433+
}
2434+
23592435
MipsAsmParser::MacroExpanderResultTy
23602436
MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
23612437
const MCSubtargetInfo *STI) {

Diff for: llvm/test/CodeGen/Mips/llvm-ir/forbidden-slot-ir.ll

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
target triple = "mipsisa32r6el-unknown-linux-gnu"
2+
3+
; RUN: llc -filetype=asm %s -o - | FileCheck %s --check-prefix=MIPSELR6
4+
; Function Attrs: noinline nounwind optnone uwtable
5+
define i1 @foo0() nounwind {
6+
; MIPSELR6: bnezc $1, $BB0_2
7+
; MIPSELR6-NEXT: nop
8+
; MIPSELR6: jr $ra
9+
entry:
10+
%0 = icmp eq i32 0, 1
11+
br i1 %0, label %2, label %3
12+
ret i1 %0
13+
2:
14+
ret i1 %0
15+
3:
16+
ret i1 %0
17+
}
18+
19+
define i32 @foo1() nounwind {
20+
; MIPSELR6: addiu $2, $2, 1
21+
; MIPSELR6-NEXT: .set noreorder
22+
; MIPSELR6-NEXT: beqzc $2, $tmp0
23+
; MIPSELR6-NEXT: nop
24+
; MIPSELR6-NEXT: .set reorder
25+
; MIPSELR6: jrc $ra
26+
entry:
27+
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b", "=r"() nounwind
28+
ret i32 %0
29+
}
30+
31+
define i32 @foo2() nounwind {
32+
; MIPSELR6: .set push
33+
; MIPSELR6-NEXT: .set at
34+
; MIPSELR6-NEXT: .set macro
35+
; MIPSELR6-NEXT: .set reorder
36+
; MIPSELR6: .set noreorder
37+
; MIPSELR6-NEXT: beqzc $9, End
38+
; MIPSELR6-NEXT: nop
39+
; MIPSELR6-NEXT: .set reorder
40+
; MIPSELR6: addiu $9, $9, 1
41+
entry:
42+
%0 = tail call i32 asm "beqzc $$t1, End", "=r"() nounwind
43+
%1 = tail call i32 asm "addiu $$t1, $$t1, 1", "=r"() nounwind
44+
%2 = add nsw i32 %1, %0
45+
ret i32 %2
46+
}
47+
48+
define i32 @foo3() nounwind {
49+
; MIPSELR6: addiu $2, $2, 1
50+
; MIPSELR6-NEXT: .set noreorder
51+
; MIPSELR6-NEXT: beqzc $2, $tmp1
52+
; MIPSELR6-NEXT: nop
53+
; MIPSELR6-NEXT: .set noreorder
54+
; MIPSELR6-NEXT: j End
55+
; MIPSELR6-NEXT: nop
56+
; MIPSELR6-NEXT: .set reorder
57+
entry:
58+
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; j End", "=r"() nounwind
59+
ret i32 %0
60+
}
61+
62+
define i32 @foo4() nounwind {
63+
; MIPSELR6: addiu $2, $2, 1
64+
; MIPSELR6-NEXT: .set noreorder
65+
; MIPSELR6-NEXT: beqzc $2, $tmp2
66+
; MIPSELR6-NEXT: addiu $2, $2, 1
67+
; MIPSELR6-NEXT: .set reorder
68+
entry:
69+
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; addiu $0, $0, 1", "=r"() nounwind
70+
ret i32 %0
71+
}

Diff for: llvm/test/MC/Mips/forbidden-slot.s

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# RUN: llvm-mc -assemble -mcpu=mips64r6 -arch=mips64el -filetype=obj %s -o tmp.o
2+
# RUN: llvm-objdump -d tmp.o | FileCheck %s --check-prefix=MIPSELR6
3+
4+
# MIPSELR6: 0000000000000000 <aaa>:
5+
# MIPSELR6-NEXT: beqzc $13, 0x0 <aaa>
6+
# MIPSELR6-NEXT: b 0x0 <aaa>
7+
# MIPSELR6: 0000000000000008 <bbb>:
8+
# MIPSELR6-NEXT: beqzc $13, 0x8 <bbb>
9+
# MIPSELR6-NEXT: nop <aaa>
10+
# MIPSELR6: b 0x8 <bbb>
11+
.set noreorder
12+
aaa:
13+
beqzc $t1, aaa
14+
b aaa
15+
.set reorder
16+
bbb:
17+
beqzc $t1, bbb
18+
b bbb

Diff for: llvm/test/MC/Mips/mips32r6/relocations.s

+11-11
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,17 @@
5252
# CHECK-ELF: Relocations [
5353
# CHECK-ELF: 0x0 R_MIPS_PC19_S2 bar
5454
# CHECK-ELF: 0x4 R_MIPS_PC16 bar
55-
# CHECK-ELF: 0x8 R_MIPS_PC16 bar
56-
# CHECK-ELF: 0xC R_MIPS_PC21_S2 bar
57-
# CHECK-ELF: 0x10 R_MIPS_PC21_S2 bar
58-
# CHECK-ELF: 0x14 R_MIPS_PC26_S2 bar
59-
# CHECK-ELF: 0x18 R_MIPS_PC26_S2 bar
60-
# CHECK-ELF: 0x1C R_MIPS_PCHI16 bar
61-
# CHECK-ELF: 0x20 R_MIPS_PCLO16 bar
62-
# CHECK-ELF: 0x24 R_MIPS_PC19_S2 bar
63-
# CHECK-ELF: 0x28 R_MIPS_PC19_S2 bar
64-
# CHECK-ELF: 0x2C R_MIPS_LO16 bar
65-
# CHECK-ELF: 0x30 R_MIPS_LO16 bar
55+
# CHECK-ELF: 0xC R_MIPS_PC16 bar
56+
# CHECK-ELF: 0x14 R_MIPS_PC21_S2 bar
57+
# CHECK-ELF: 0x1C R_MIPS_PC21_S2 bar
58+
# CHECK-ELF: 0x24 R_MIPS_PC26_S2 bar
59+
# CHECK-ELF: 0x28 R_MIPS_PC26_S2 bar
60+
# CHECK-ELF: 0x2C R_MIPS_PCHI16 bar
61+
# CHECK-ELF: 0x30 R_MIPS_PCLO16 bar
62+
# CHECK-ELF: 0x34 R_MIPS_PC19_S2 bar
63+
# CHECK-ELF: 0x38 R_MIPS_PC19_S2 bar
64+
# CHECK-ELF: 0x3C R_MIPS_LO16 bar
65+
# CHECK-ELF: 0x40 R_MIPS_LO16 bar
6666
# CHECK-ELF: ]
6767

6868
addiupc $2,bar

Diff for: llvm/test/MC/Mips/mips64r6/relocations.s

+13-13
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@
5959
# CHECK-ELF: Relocations [
6060
# CHECK-ELF: 0x0 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
6161
# CHECK-ELF: 0x4 R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
62-
# CHECK-ELF: 0x8 R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
63-
# CHECK-ELF: 0xC R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
64-
# CHECK-ELF: 0x10 R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
65-
# CHECK-ELF: 0x14 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
66-
# CHECK-ELF: 0x18 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
67-
# CHECK-ELF: 0x1C R_MIPS_PCHI16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
68-
# CHECK-ELF: 0x20 R_MIPS_PCLO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
69-
# CHECK-ELF: 0x24 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
70-
# CHECK-ELF: 0x28 R_MIPS_PC18_S3/R_MIPS_NONE/R_MIPS_NONE bar 0x0
71-
# CHECK-ELF: 0x2C R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
72-
# CHECK-ELF: 0x30 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
73-
# CHECK-ELF: 0x34 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
74-
# CHECK-ELF: 0x38 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
62+
# CHECK-ELF: 0xC R_MIPS_PC16/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
63+
# CHECK-ELF: 0x14 R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
64+
# CHECK-ELF: 0x1C R_MIPS_PC21_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
65+
# CHECK-ELF: 0x24 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
66+
# CHECK-ELF: 0x28 R_MIPS_PC26_S2/R_MIPS_NONE/R_MIPS_NONE bar 0xFFFFFFFFFFFFFFFC
67+
# CHECK-ELF: 0x2C R_MIPS_PCHI16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
68+
# CHECK-ELF: 0x30 R_MIPS_PCLO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
69+
# CHECK-ELF: 0x34 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
70+
# CHECK-ELF: 0x38 R_MIPS_PC18_S3/R_MIPS_NONE/R_MIPS_NONE bar 0x0
71+
# CHECK-ELF: 0x3C R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
72+
# CHECK-ELF: 0x40 R_MIPS_PC19_S2/R_MIPS_NONE/R_MIPS_NONE bar 0x0
73+
# CHECK-ELF: 0x44 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
74+
# CHECK-ELF: 0x48 R_MIPS_LO16/R_MIPS_NONE/R_MIPS_NONE bar 0x0
7575
# CHECK-ELF: ]
7676

7777
addiupc $2,bar

Diff for: llvm/test/MC/Mips/relocation.s

+2-2
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ baz: .long foo // RELOC: R_MIPS_32 foo
237237
// ENCLE: addiu $2, $3, %tprel_lo(foo) # encoding: [A,A,0x62,0x24]
238238
// FIXUP: # fixup A - offset: 0, value: %tprel_lo(foo), kind: fixup_Mips_TPREL_LO
239239

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

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

0 commit comments

Comments
 (0)