diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 1f427638e099c3..bc239480baa891 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -220,6 +220,7 @@ class SparcOperand : public MCParsedAsmOperand { k_MemoryImm, k_ASITag, k_PrefetchTag, + k_TailRelocSym, // Special kind of immediate for TLS relocation purposes. } Kind; SMLoc StartLoc, EndLoc; @@ -265,7 +266,7 @@ class SparcOperand : public MCParsedAsmOperand { 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 @@ class SparcOperand : public MCParsedAsmOperand { 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 @@ class SparcOperand : public MCParsedAsmOperand { case k_PrefetchTag: OS << "Prefetch tag: " << getPrefetchTag() << "\n"; break; + case k_TailRelocSym: + OS << "TailReloc: " << getTailRelocSym() << "\n"; + break; } } @@ -454,7 +463,7 @@ class SparcOperand : public MCParsedAsmOperand { void addTailRelocSymOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - addExpr(Inst, getImm()); + addExpr(Inst, getTailRelocSym()); } static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { @@ -503,6 +512,15 @@ class SparcOperand : public MCParsedAsmOperand { return Op; } + static std::unique_ptr CreateTailRelocSym(const MCExpr *Val, + SMLoc S, SMLoc E) { + auto Op = std::make_unique(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 403c924769385c..7c84c4ac1b4615 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 bb5b9f2d736f93..c3b1fdf14d73ec 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 109e7c9b011487..05a691de4f9669 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