Skip to content

Commit 7689da7

Browse files
committed
[Mips] Fix unable to handle inline assembly ends with compat-branch on 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.
1 parent a90ed3e commit 7689da7

File tree

7 files changed

+176
-35
lines changed

7 files changed

+176
-35
lines changed

lld/test/ELF/mips-pc-relocs.s

Lines changed: 10 additions & 8 deletions
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)

llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

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

23132360
MacroExpanderResultTy ExpandResult =
@@ -2322,6 +2369,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23222369
return true;
23232370
}
23242371

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

23322390
// If this instruction has a delay slot and .set reorder is active,
23332391
// emit a NOP after it.
2392+
// The format of the third case is:
2393+
// .set noreorder
2394+
// bnezc
2395+
// nop
2396+
// .set noreorder
2397+
// j
2398+
// nop
2399+
// .set reorder
23342400
if (FillDelaySlot) {
23352401
TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst), IDLoc, STI);
23362402
TOut.emitDirectiveSetReorder();
@@ -2356,6 +2422,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
23562422
return false;
23572423
}
23582424

2425+
void MipsAsmParser::onEndOfFile() {
2426+
MipsTargetStreamer &TOut = getTargetStreamer();
2427+
SMLoc IDLoc = SMLoc();
2428+
// If has pending forbidden slot, fill nop and recover reorder.
2429+
if (CurForbiddenSlotAttr) {
2430+
TOut.emitEmptyDelaySlot(false, IDLoc, STI);
2431+
if (AssemblerOptions.back()->isReorder())
2432+
TOut.emitDirectiveSetReorder();
2433+
}
2434+
}
2435+
23592436
MipsAsmParser::MacroExpanderResultTy
23602437
MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
23612438
const MCSubtargetInfo *STI) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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: beqzc $2, $tmp0
21+
; MIPSELR6-NEXT: nop
22+
; MIPSELR6: jrc $ra
23+
entry:
24+
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b", "=r"() nounwind
25+
ret i32 %0
26+
}
27+
28+
define i32 @foo2() nounwind {
29+
; MIPSELR6: beqzc $9, End
30+
; MIPSELR6-NEXT: nop
31+
; MIPSELR6: addiu $9, $9, 1
32+
entry:
33+
%0 = tail call i32 asm "beqzc $$t1, End", "=r"() nounwind
34+
%1 = tail call i32 asm "addiu $$t1, $$t1, 1", "=r"() nounwind
35+
%2 = add nsw i32 %1, %0
36+
ret i32 %2
37+
}
38+
39+
define i32 @foo3() nounwind {
40+
; MIPSELR6: beqzc $2, $tmp1
41+
; MIPSELR6-NEXT: nop
42+
; MIPSELR6: j End
43+
entry:
44+
%0 = tail call i32 asm "1: addiu $0, $0, 1; beqzc $0, 1b; j End", "=r"() nounwind
45+
ret i32 %0
46+
}

llvm/test/MC/Mips/forbidden-slot.s

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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: beqzc $13, 0x0 <aaa>
5+
# MIPSELR6-NEXT: b 0x0 <aaa>
6+
# MIPSELR6: beqzc $13, 0x8 <bbb>
7+
# MIPSELR6-NEXT: nop <aaa>
8+
# MIPSELR6: b 0x8 <bbb>
9+
.set noreorder
10+
aaa:
11+
beqzc $t1, aaa
12+
b aaa
13+
.set reorder
14+
bbb:
15+
beqzc $t1, bbb
16+
b bbb

llvm/test/MC/Mips/mips32r6/relocations.s

Lines changed: 11 additions & 11 deletions
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

llvm/test/MC/Mips/mips64r6/relocations.s

Lines changed: 13 additions & 13 deletions
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

llvm/test/MC/Mips/relocation.s

Lines changed: 2 additions & 2 deletions
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)