Skip to content

[LoongArch] Emit function call code sequence as PCADDU18I+JIRL in medium code model #76555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ class LoongArchAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo instruction "li.w/d $rd, $imm".
void emitLoadImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);

// Helper to emit pseudo instruction "call36 sym" or "tail36 $rj, sym".
void emitFuncCall36(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool IsTailCall);

public:
enum LoongArchMatchResultTy {
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
Expand Down Expand Up @@ -400,6 +404,22 @@ class LoongArchOperand : public MCParsedAsmOperand {
IsValidKind;
}

bool isSImm20pcaddu18i() const {
if (!isImm())
return false;

int64_t Imm;
LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
VK == LoongArchMCExpr::VK_LoongArch_CALL36;

return IsConstantImm
? isInt<20>(Imm) && IsValidKind
: LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
IsValidKind;
}

bool isSImm21lsl2() const {
if (!isImm())
return false;
Expand Down Expand Up @@ -1110,6 +1130,35 @@ void LoongArchAsmParser::emitLoadImm(MCInst &Inst, SMLoc IDLoc,
}
}

void LoongArchAsmParser::emitFuncCall36(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out, bool IsTailCall) {
// call36 sym
// expands to:
// pcaddu18i $ra, %call36(sym)
// jirl $ra, $ra, 0
//
// tail36 $rj, sym
// expands to:
// pcaddu18i $rj, %call36(sym)
// jirl $r0, $rj, 0
unsigned ScratchReg =
IsTailCall ? Inst.getOperand(0).getReg() : (unsigned)LoongArch::R1;
const MCExpr *Sym =
IsTailCall ? Inst.getOperand(1).getExpr() : Inst.getOperand(0).getExpr();
const LoongArchMCExpr *LE = LoongArchMCExpr::create(
Sym, llvm::LoongArchMCExpr::VK_LoongArch_CALL36, getContext());

Out.emitInstruction(
MCInstBuilder(LoongArch::PCADDU18I).addReg(ScratchReg).addExpr(LE),
getSTI());
Out.emitInstruction(
MCInstBuilder(LoongArch::JIRL)
.addReg(IsTailCall ? (unsigned)LoongArch::R0 : ScratchReg)
.addReg(ScratchReg)
.addImm(0),
getSTI());
}

bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
OperandVector &Operands,
MCStreamer &Out) {
Expand Down Expand Up @@ -1158,6 +1207,12 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case LoongArch::PseudoLI_D:
emitLoadImm(Inst, IDLoc, Out);
return false;
case LoongArch::PseudoCALL36:
emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/false);
return false;
case LoongArch::PseudoTAIL36:
emitFuncCall36(Inst, IDLoc, Out, /*IsTailCall=*/true);
return false;
}
Out.emitInstruction(Inst, getSTI());
return false;
Expand Down Expand Up @@ -1439,6 +1494,12 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
/*Upper=*/(1 << 19) - 1,
"operand must be a symbol with modifier (e.g. %pc_hi20) or an integer "
"in the range");
case Match_InvalidSImm20pcaddu18i:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 19),
/*Upper=*/(1 << 19) - 1,
"operand must be a symbol with modifier (e.g. %call36) or an integer "
"in the range");
case Match_InvalidSImm21lsl2:
return generateImmOutOfRangeError(
Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
Expand Down
Loading