diff options
author | Koakuma <koachan@protonmail.com> | 2024-12-17 10:42:26 +0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-17 10:42:26 +0700 |
commit | ad64946549e377e5cfdcfe84081149b7aa17c4d6 (patch) | |
tree | 3c94b4e6f2dca3f4d5744c2aeaac7b602be74632 | |
parent | 5e1f87e849d1f94f3e8baf190be20219edf44584 (diff) | |
download | llvm-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.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/DelaySlotFiller.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.td | 20 | ||||
-rw-r--r-- | llvm/test/MC/Sparc/sparc-ctrl-instructions.s | 21 |
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 |