aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2024-12-17 10:42:26 +0700
committerGitHub <noreply@github.com>2024-12-17 10:42:26 +0700
commitad64946549e377e5cfdcfe84081149b7aa17c4d6 (patch)
tree3c94b4e6f2dca3f4d5744c2aeaac7b602be74632
parent5e1f87e849d1f94f3e8baf190be20219edf44584 (diff)
downloadllvm-ad64946549e377e5cfdcfe84081149b7aa17c4d6.zip
llvm-ad64946549e377e5cfdcfe84081149b7aa17c4d6.tar.gz
llvm-ad64946549e377e5cfdcfe84081149b7aa17c4d6.tar.bz2
[SPARC][IAS] Add support for `call dest, imm` form (#119078)
This follows GCC behavior of allowing a trailing immediate, that is ignored by the assembler.
-rw-r--r--llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp26
-rw-r--r--llvm/lib/Target/Sparc/DelaySlotFiller.cpp11
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.td20
-rw-r--r--llvm/test/MC/Sparc/sparc-ctrl-instructions.s21
4 files changed, 71 insertions, 7 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 1f42763..bc23948 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -220,6 +220,7 @@ private:
k_MemoryImm,
k_ASITag,
k_PrefetchTag,
+ k_TailRelocSym, // Special kind of immediate for TLS relocation purposes.
} Kind;
SMLoc StartLoc, EndLoc;
@@ -265,7 +266,7 @@ public:
bool isMembarTag() const { return Kind == k_Immediate; }
bool isASITag() const { return Kind == k_ASITag; }
bool isPrefetchTag() const { return Kind == k_PrefetchTag; }
- bool isTailRelocSym() const { return Kind == k_Immediate; }
+ bool isTailRelocSym() const { return Kind == k_TailRelocSym; }
bool isCallTarget() const {
if (!isImm())
@@ -354,6 +355,11 @@ public:
return Prefetch;
}
+ const MCExpr *getTailRelocSym() const {
+ assert((Kind == k_TailRelocSym) && "Invalid access!");
+ return Imm.Val;
+ }
+
/// getStartLoc - Get the location of the first token of this operand.
SMLoc getStartLoc() const override {
return StartLoc;
@@ -380,6 +386,9 @@ public:
case k_PrefetchTag:
OS << "Prefetch tag: " << getPrefetchTag() << "\n";
break;
+ case k_TailRelocSym:
+ OS << "TailReloc: " << getTailRelocSym() << "\n";
+ break;
}
}
@@ -454,7 +463,7 @@ public:
void addTailRelocSymOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
- addExpr(Inst, getImm());
+ addExpr(Inst, getTailRelocSym());
}
static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
@@ -503,6 +512,15 @@ public:
return Op;
}
+ static std::unique_ptr<SparcOperand> CreateTailRelocSym(const MCExpr *Val,
+ SMLoc S, SMLoc E) {
+ auto Op = std::make_unique<SparcOperand>(k_TailRelocSym);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
static bool MorphToIntPairReg(SparcOperand &Op) {
unsigned Reg = Op.getReg();
assert(Op.Reg.Kind == rk_IntReg);
@@ -1070,7 +1088,7 @@ ParseStatus SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
};
if (getLexer().getKind() != AsmToken::Percent)
- return Error(getLoc(), "expected '%' for operand modifier");
+ return ParseStatus::NoMatch;
const AsmToken Tok = Parser.getTok();
getParser().Lex(); // Eat '%'
@@ -1099,7 +1117,7 @@ ParseStatus SparcAsmParser::parseTailRelocSym(OperandVector &Operands) {
return ParseStatus::Failure;
const MCExpr *Val = adjustPICRelocation(VK, SubExpr);
- Operands.push_back(SparcOperand::CreateImm(Val, S, E));
+ Operands.push_back(SparcOperand::CreateTailRelocSym(Val, S, E));
return ParseStatus::Success;
}
diff --git a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
index 403c924..7c84c4a 100644
--- a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
+++ b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
@@ -309,7 +309,8 @@ void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI,
switch(MI->getOpcode()) {
default: llvm_unreachable("Unknown opcode.");
- case SP::CALL: break;
+ case SP::CALL:
+ break;
case SP::CALLrr:
case SP::CALLri:
assert(MI->getNumOperands() >= 2);
@@ -371,9 +372,13 @@ bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
unsigned structSizeOpNum = 0;
switch (I->getOpcode()) {
default: llvm_unreachable("Unknown call opcode.");
- case SP::CALL: structSizeOpNum = 1; break;
+ case SP::CALL:
+ structSizeOpNum = 1;
+ break;
case SP::CALLrr:
- case SP::CALLri: structSizeOpNum = 2; break;
+ case SP::CALLri:
+ structSizeOpNum = 2;
+ break;
case SP::TLS_CALL: return false;
case SP::TAIL_CALLri:
case SP::TAIL_CALL: return false;
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td
index bb5b9f2d..c3b1fdf 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -1036,6 +1036,17 @@ let Uses = [O6],
let Inst{29-0} = disp;
}
+ // call with trailing imm argument.
+ // The imm argument is discarded.
+ let isAsmParserOnly = 1 in {
+ def CALLi : InstSP<(outs), (ins calltarget:$disp, i32imm:$imm),
+ "call $disp, $imm", []> {
+ bits<30> disp;
+ let op = 1;
+ let Inst{29-0} = disp;
+ }
+ }
+
// indirect calls: special cases of JMPL.
let isCodeGenOnly = 1, rd = 15 in {
def CALLrr : F3_1<2, 0b111000,
@@ -1049,6 +1060,15 @@ let Uses = [O6],
[(call ADDRri:$addr)],
IIC_jmp_or_call>;
}
+
+ let isAsmParserOnly = 1, rd = 15 in {
+ def CALLrri : F3_1<2, 0b111000,
+ (outs), (ins (MEMrr $rs1, $rs2):$addr, i32imm:$imm),
+ "call $addr, $imm", []>;
+ def CALLrii : F3_2<2, 0b111000,
+ (outs), (ins (MEMri $rs1, $simm13):$addr, i32imm:$imm),
+ "call $addr, $imm", []>;
+ }
}
// Section B.25 - Jump and Link Instruction
diff --git a/llvm/test/MC/Sparc/sparc-ctrl-instructions.s b/llvm/test/MC/Sparc/sparc-ctrl-instructions.s
index 109e7c9b..05a691d 100644
--- a/llvm/test/MC/Sparc/sparc-ctrl-instructions.s
+++ b/llvm/test/MC/Sparc/sparc-ctrl-instructions.s
@@ -5,23 +5,44 @@
! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30
call foo
+ ! CHECK: call foo, 0 ! encoding: [0b01AAAAAA,A,A,A]
+ ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30
+ call foo, 0
+
! CHECK: call %g1+%i2 ! encoding: [0x9f,0xc0,0x40,0x1a]
call %g1 + %i2
+ ! CHECK: call %g1+%i2, 1 ! encoding: [0x9f,0xc0,0x40,0x1a]
+ call %g1 + %i2, 1
+
! CHECK: call %o1+8 ! encoding: [0x9f,0xc2,0x60,0x08]
call %o1 + 8
+ ! CHECK: call %o1+8, 2 ! encoding: [0x9f,0xc2,0x60,0x08]
+ call %o1 + 8, 2
+
! CHECK: call %g1 ! encoding: [0x9f,0xc0,0x40,0x00]
call %g1
+ ! CHECK: call %g1, 3 ! encoding: [0x9f,0xc0,0x40,0x00]
+ call %g1, 3
+
! CHECK: call %g1+%lo(sym) ! encoding: [0x9f,0xc0,0b011000AA,A]
! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
call %g1+%lo(sym)
+ ! CHECK: call %g1+%lo(sym), 4 ! encoding: [0x9f,0xc0,0b011000AA,A]
+ ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
+ call %g1+%lo(sym), 4
+
! CHECK-LABEL: .Ltmp0:
! CHECK: call .Ltmp0-4 ! encoding: [0b01AAAAAA,A,A,A]
call . - 4
+ ! CHECK-LABEL: .Ltmp1:
+ ! CHECK: call .Ltmp1-4, 5 ! encoding: [0b01AAAAAA,A,A,A]
+ call . - 4, 5
+
! CHECK: jmp %g1+%i2 ! encoding: [0x81,0xc0,0x40,0x1a]
jmp %g1 + %i2