diff options
author | wanglei <wanglei@loongson.cn> | 2024-07-26 14:36:54 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-26 14:36:54 +0800 |
commit | e27358c8ed7abac200546e808ea30a86aa9aa580 (patch) | |
tree | d109f69e904ce56e7271b253f78f97bbf4dc2281 | |
parent | 63d088c6e46122bc776f89ded4f285feaab69ae6 (diff) | |
download | llvm-e27358c8ed7abac200546e808ea30a86aa9aa580.zip llvm-e27358c8ed7abac200546e808ea30a86aa9aa580.tar.gz llvm-e27358c8ed7abac200546e808ea30a86aa9aa580.tar.bz2 |
[LoongArch][MC] Support %[ld_/gd_/desc_]pcrel_20
Reviewed By: SixWeining, MaskRay
Pull Request: https://github.com/llvm/llvm-project/pull/100104
8 files changed, 92 insertions, 3 deletions
diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp index 208bd3d..f52e188 100644 --- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp @@ -450,6 +450,24 @@ public: IsValidKind; } + bool isSImm20pcaddi() 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_PCREL20_S2 || + VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2 || + VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2 || + VK == LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2; + return IsConstantImm + ? isInt<20>(Imm) && IsValidKind + : LoongArchAsmParser::classifySymbolRef(getImm(), VK) && + IsValidKind; + } + bool isSImm21lsl2() const { if (!isImm()) return false; @@ -1676,6 +1694,12 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, /*Upper=*/(1 << 19) - 1, "operand must be a symbol with modifier (e.g. %call36) or an integer " "in the range"); + case Match_InvalidSImm20pcaddi: + return generateImmOutOfRangeError( + Operands, ErrorInfo, /*Lower=*/-(1 << 19), + /*Upper=*/(1 << 19) - 1, + "operand must be a symbol with modifier (e.g. %pcrel_20) or an integer " + "in the range"); case Match_InvalidSImm21lsl2: return generateImmOutOfRangeError( Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index ec0d0714..ef647a4 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -397,6 +397,10 @@ def simm20_pcaddu18i : SImm20Operand { let ParserMatchClass = SImmAsmOperand<20, "pcaddu18i">; } +def simm20_pcaddi : SImm20Operand { + let ParserMatchClass = SImmAsmOperand<20, "pcaddi">; +} + def simm21_lsl2 : Operand<OtherVT> { let ParserMatchClass = SImmAsmOperand<21, "lsl2">; let EncoderMethod = "getImmOpValueAsr<2>"; @@ -754,7 +758,7 @@ def SLT : ALU_3R<0x00120000>; def SLTU : ALU_3R<0x00128000>; def SLTI : ALU_2RI12<0x02000000, simm12>; def SLTUI : ALU_2RI12<0x02400000, simm12>; -def PCADDI : ALU_1RI20<0x18000000, simm20>; +def PCADDI : ALU_1RI20<0x18000000, simm20_pcaddi>; def PCADDU12I : ALU_1RI20<0x1c000000, simm20>; def PCALAU12I : ALU_1RI20<0x1a000000, simm20_pcalau12i>; def AND : ALU_3R<0x00148000>; diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h index 29ed14f..370f5b0 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h @@ -111,6 +111,8 @@ enum Fixups { fixup_loongarch_relax = FirstLiteralRelocationKind + ELF::R_LARCH_RELAX, // Generate an R_LARCH_ALIGN which indicates the linker may fixup align here. fixup_loongarch_align = FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN, + // 20-bit fixup corresponding to %pcrel_20(foo) for instruction pcaddi. + fixup_loongarch_pcrel20_s2, // 36-bit fixup corresponding to %call36(foo) for a pair instructions: // pcaddu18i+jirl. fixup_loongarch_call36 = FirstLiteralRelocationKind + ELF::R_LARCH_CALL36, @@ -142,6 +144,12 @@ enum Fixups { fixup_loongarch_tls_le_add_r, // 12-bit fixup corresponding to %le_lo12_r(foo) for instruction addi.w/d. fixup_loongarch_tls_le_lo12_r, + // 20-bit fixup corresponding to %ld_pcrel_20(foo) for instruction pcaddi. + fixup_loongarch_tls_ld_pcrel20_s2, + // 20-bit fixup corresponding to %gd_pcrel_20(foo) for instruction pcaddi. + fixup_loongarch_tls_gd_pcrel20_s2, + // 20-bit fixup corresponding to %desc_pcrel_20(foo) for instruction pcaddi. + fixup_loongarch_tls_desc_pcrel20_s2, }; } // end namespace LoongArch } // end namespace llvm diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp index efbfce3..4f7f93f 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp @@ -287,6 +287,18 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO, case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R: FixupKind = LoongArch::fixup_loongarch_tls_le_lo12_r; break; + case LoongArchMCExpr::VK_LoongArch_PCREL20_S2: + FixupKind = LoongArch::fixup_loongarch_pcrel20_s2; + break; + case LoongArchMCExpr::VK_LoongArch_TLS_LD_PCREL20_S2: + FixupKind = LoongArch::fixup_loongarch_tls_ld_pcrel20_s2; + break; + case LoongArchMCExpr::VK_LoongArch_TLS_GD_PCREL20_S2: + FixupKind = LoongArch::fixup_loongarch_tls_gd_pcrel20_s2; + break; + case LoongArchMCExpr::VK_LoongArch_TLS_DESC_PCREL20_S2: + FixupKind = LoongArch::fixup_loongarch_tls_desc_pcrel20_s2; + break; } } else if (Kind == MCExpr::SymbolRef && cast<MCSymbolRefExpr>(Expr)->getKind() == diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp index 98b9b1a..53d46cc 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp @@ -166,6 +166,14 @@ StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) { return "le_add_r"; case VK_LoongArch_TLS_LE_LO12_R: return "le_lo12_r"; + case VK_LoongArch_PCREL20_S2: + return "pcrel_20"; + case VK_LoongArch_TLS_LD_PCREL20_S2: + return "ld_pcrel_20"; + case VK_LoongArch_TLS_GD_PCREL20_S2: + return "gd_pcrel_20"; + case VK_LoongArch_TLS_DESC_PCREL20_S2: + return "desc_pcrel_20"; } } @@ -222,6 +230,10 @@ LoongArchMCExpr::getVariantKindForName(StringRef name) { .Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R) .Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R) .Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R) + .Case("pcrel_20", VK_LoongArch_PCREL20_S2) + .Case("ld_pcrel_20", VK_LoongArch_TLS_LD_PCREL20_S2) + .Case("gd_pcrel_20", VK_LoongArch_TLS_GD_PCREL20_S2) + .Case("desc_pcrel_20", VK_LoongArch_TLS_DESC_PCREL20_S2) .Default(VK_LoongArch_Invalid); } @@ -264,6 +276,9 @@ void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { case VK_LoongArch_TLS_GD_HI20: case VK_LoongArch_TLS_DESC_PC_HI20: case VK_LoongArch_TLS_DESC_HI20: + case VK_LoongArch_TLS_LD_PCREL20_S2: + case VK_LoongArch_TLS_GD_PCREL20_S2: + case VK_LoongArch_TLS_DESC_PCREL20_S2: break; } fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h index 1546d89..91215b8 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h @@ -75,6 +75,10 @@ public: VK_LoongArch_TLS_LE_HI20_R, VK_LoongArch_TLS_LE_ADD_R, VK_LoongArch_TLS_LE_LO12_R, + VK_LoongArch_PCREL20_S2, + VK_LoongArch_TLS_LD_PCREL20_S2, + VK_LoongArch_TLS_GD_PCREL20_S2, + VK_LoongArch_TLS_DESC_PCREL20_S2, VK_LoongArch_Invalid // Must be the last item. }; diff --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s index 958d5cab..08a131d 100644 --- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s +++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s @@ -99,11 +99,13 @@ jirl $a0, $a0, 0x20000 # CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068] ## simm20 -pcaddi $a0, -0x80001 -# CHECK: :[[#@LINE-1]]:13: error: immediate must be an integer in the range [-524288, 524287] pcaddu12i $a0, 0x80000 # CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287] +## simm20_pcaddi +pcaddi $a0, -0x80001 +# CHECK: :[[#@LINE-1]]:13: error: operand must be a symbol with modifier (e.g. %pcrel_20) or an integer in the range [-524288, 524287] + ## simm20_lu12iw lu12i.w $a0, -0x80001 # CHECK: :[[#@LINE-1]]:14: error: operand must be a symbol with modifier (e.g. %abs_hi20) or an integer in the range [-524288, 524287] diff --git a/llvm/test/MC/LoongArch/Relocations/relocations.s b/llvm/test/MC/LoongArch/Relocations/relocations.s index e83b671..091dce2 100644 --- a/llvm/test/MC/LoongArch/Relocations/relocations.s +++ b/llvm/test/MC/LoongArch/Relocations/relocations.s @@ -288,3 +288,23 @@ addi.d $t1, $a2, %le_lo12_r(foo) # RELOC: R_LARCH_TLS_LE_LO12_R foo 0x0 # INSTR: addi.d $t1, $a2, %le_lo12_r(foo) # FIXUP: fixup A - offset: 0, value: %le_lo12_r(foo), kind: FK_NONE + +pcaddi $t1, %pcrel_20(foo) +# RELOC: R_LARCH_PCREL20_S2 foo 0x0 +# INSTR: pcaddi $t1, %pcrel_20(foo) +# FIXUP: fixup A - offset: 0, value: %pcrel_20(foo), kind: FK_NONE + +pcaddi $t1, %ld_pcrel_20(foo) +# RELOC: R_LARCH_TLS_LD_PCREL20_S2 foo 0x0 +# INSTR: pcaddi $t1, %ld_pcrel_20(foo) +# FIXUP: fixup A - offset: 0, value: %ld_pcrel_20(foo), kind: FK_NONE + +pcaddi $t1, %gd_pcrel_20(foo) +# RELOC: R_LARCH_TLS_GD_PCREL20_S2 foo 0x0 +# INSTR: pcaddi $t1, %gd_pcrel_20(foo) +# FIXUP: fixup A - offset: 0, value: %gd_pcrel_20(foo), kind: FK_NONE + +pcaddi $t1, %desc_pcrel_20(foo) +# RELOC: R_LARCH_TLS_DESC_PCREL20_S2 foo 0x0 +# INSTR: pcaddi $t1, %desc_pcrel_20(foo) +# FIXUP: fixup A - offset: 0, value: %desc_pcrel_20(foo), kind: FK_NONE |