@@ -645,6 +645,203 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
645645 }
646646}
647647
648+ bool RuntimeDyldELF::resolveLoongArch64ShortBranch (
649+ unsigned SectionID, relocation_iterator RelI,
650+ const RelocationValueRef &Value) {
651+ uint64_t Address;
652+ if (Value.SymbolName ) {
653+ auto Loc = GlobalSymbolTable.find (Value.SymbolName );
654+ // Don't create direct branch for external symbols.
655+ if (Loc == GlobalSymbolTable.end ())
656+ return false ;
657+ const auto &SymInfo = Loc->second ;
658+ Address =
659+ uint64_t (Sections[SymInfo.getSectionID ()].getLoadAddressWithOffset (
660+ SymInfo.getOffset ()));
661+ } else {
662+ Address = uint64_t (Sections[Value.SectionID ].getLoadAddress ());
663+ }
664+ uint64_t Offset = RelI->getOffset ();
665+ uint64_t SourceAddress = Sections[SectionID].getLoadAddressWithOffset (Offset);
666+ if (!isInt<28 >(Address + Value.Addend - SourceAddress))
667+ return false ;
668+ resolveRelocation (Sections[SectionID], Offset, Address, RelI->getType (),
669+ Value.Addend );
670+ return true ;
671+ }
672+
673+ void RuntimeDyldELF::resolveLoongArch64Branch (unsigned SectionID,
674+ const RelocationValueRef &Value,
675+ relocation_iterator RelI,
676+ StubMap &Stubs) {
677+ LLVM_DEBUG (dbgs () << " \t\t This is an LoongArch64 branch relocation.\n " );
678+ SectionEntry &Section = Sections[SectionID];
679+ uint64_t Offset = RelI->getOffset ();
680+ unsigned RelType = RelI->getType ();
681+ // Look for an existing stub.
682+ StubMap::const_iterator i = Stubs.find (Value);
683+ if (i != Stubs.end ()) {
684+ resolveRelocation (Section, Offset,
685+ (uint64_t )Section.getAddressWithOffset (i->second ),
686+ RelType, 0 );
687+ LLVM_DEBUG (dbgs () << " Stub function found\n " );
688+ } else if (!resolveLoongArch64ShortBranch (SectionID, RelI, Value)) {
689+ // Create a new stub function.
690+ LLVM_DEBUG (dbgs () << " Create a new stub function\n " );
691+ Stubs[Value] = Section.getStubOffset ();
692+ uint8_t *StubTargetAddr = createStubFunction (
693+ Section.getAddressWithOffset (Section.getStubOffset ()));
694+ RelocationEntry LU12I_W (SectionID, StubTargetAddr - Section.getAddress (),
695+ ELF::R_LARCH_ABS_HI20, Value.Addend );
696+ RelocationEntry ORI (SectionID, StubTargetAddr - Section.getAddress () + 4 ,
697+ ELF::R_LARCH_ABS_LO12, Value.Addend );
698+ RelocationEntry LU32I_D (SectionID,
699+ StubTargetAddr - Section.getAddress () + 8 ,
700+ ELF::R_LARCH_ABS64_LO20, Value.Addend );
701+ RelocationEntry LU52I_D (SectionID,
702+ StubTargetAddr - Section.getAddress () + 12 ,
703+ ELF::R_LARCH_ABS64_HI12, Value.Addend );
704+ if (Value.SymbolName ) {
705+ addRelocationForSymbol (LU12I_W, Value.SymbolName );
706+ addRelocationForSymbol (ORI, Value.SymbolName );
707+ addRelocationForSymbol (LU32I_D, Value.SymbolName );
708+ addRelocationForSymbol (LU52I_D, Value.SymbolName );
709+ } else {
710+ addRelocationForSection (LU12I_W, Value.SectionID );
711+ addRelocationForSection (ORI, Value.SectionID );
712+ addRelocationForSection (LU32I_D, Value.SectionID );
713+ addRelocationForSection (LU52I_D, Value.SectionID );
714+ }
715+ resolveRelocation (Section, Offset,
716+ reinterpret_cast <uint64_t >(Section.getAddressWithOffset (
717+ Section.getStubOffset ())),
718+ RelType, 0 );
719+ Section.advanceStubOffset (getMaxStubSize ());
720+ }
721+ }
722+
723+ // Returns extract bits Val[Hi:Lo].
724+ static inline uint32_t extractBits (uint64_t Val, uint32_t Hi, uint32_t Lo) {
725+ return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1 )) - 1 ))) >> Lo;
726+ }
727+
728+ void RuntimeDyldELF::resolveLoongArch64Relocation (const SectionEntry &Section,
729+ uint64_t Offset,
730+ uint64_t Value, uint32_t Type,
731+ int64_t Addend) {
732+ auto *TargetPtr = Section.getAddressWithOffset (Offset);
733+ uint64_t FinalAddress = Section.getLoadAddressWithOffset (Offset);
734+
735+ LLVM_DEBUG (dbgs () << " resolveLoongArch64Relocation, LocalAddress: 0x"
736+ << format (" %llx" , Section.getAddressWithOffset (Offset))
737+ << " FinalAddress: 0x" << format (" %llx" , FinalAddress)
738+ << " Value: 0x" << format (" %llx" , Value) << " Type: 0x"
739+ << format (" %x" , Type) << " Addend: 0x"
740+ << format (" %llx" , Addend) << " \n " );
741+
742+ switch (Type) {
743+ default :
744+ report_fatal_error (" Relocation type not implemented yet!" );
745+ break ;
746+ case ELF::R_LARCH_32:
747+ support::ulittle32_t ::ref{TargetPtr} =
748+ static_cast <uint32_t >(Value + Addend);
749+ break ;
750+ case ELF::R_LARCH_64:
751+ support::ulittle64_t ::ref{TargetPtr} = Value + Addend;
752+ break ;
753+ case ELF::R_LARCH_32_PCREL:
754+ support::ulittle32_t ::ref{TargetPtr} =
755+ static_cast <uint32_t >(Value + Addend - FinalAddress);
756+ break ;
757+ case ELF::R_LARCH_B26: {
758+ uint64_t B26 = (Value + Addend - FinalAddress) >> 2 ;
759+ auto Instr = support::ulittle32_t::ref (TargetPtr);
760+ uint32_t Imm15_0 = extractBits (B26, /* Hi=*/ 15 , /* Lo=*/ 0 ) << 10 ;
761+ uint32_t Imm25_16 = extractBits (B26, /* Hi=*/ 25 , /* Lo=*/ 16 );
762+ Instr = (Instr & 0xfc000000 ) | Imm15_0 | Imm25_16;
763+ break ;
764+ }
765+ case ELF::R_LARCH_CALL36: {
766+ uint64_t Call36 = (Value + Addend - FinalAddress) >> 2 ;
767+ auto Pcaddu18i = support::ulittle32_t::ref (TargetPtr);
768+ uint32_t Imm35_16 =
769+ extractBits ((Call36 + (1UL << 15 )), /* Hi=*/ 35 , /* Lo=*/ 16 ) << 5 ;
770+ Pcaddu18i = (Pcaddu18i & 0xfe00001f ) | Imm35_16;
771+ auto Jirl = support::ulittle32_t::ref (TargetPtr + 4 );
772+ uint32_t Imm15_0 = extractBits (Call36, /* Hi=*/ 15 , /* Lo=*/ 0 ) << 10 ;
773+ Jirl = (Jirl & 0xfc0003ff ) | Imm15_0;
774+ break ;
775+ }
776+ case ELF::R_LARCH_GOT_PC_HI20:
777+ case ELF::R_LARCH_PCALA_HI20: {
778+ uint64_t Target = Value + Addend;
779+ uint64_t TargetPage =
780+ (Target + (Target & 0x800 )) & ~static_cast <uint64_t >(0xfff );
781+ uint64_t PCPage = FinalAddress & ~static_cast <uint64_t >(0xfff );
782+ int64_t PageDelta = TargetPage - PCPage;
783+ auto Instr = support::ulittle32_t::ref (TargetPtr);
784+ uint32_t Imm31_12 = extractBits (PageDelta, /* Hi=*/ 31 , /* Lo=*/ 12 ) << 5 ;
785+ Instr = (Instr & 0xfe00001f ) | Imm31_12;
786+ break ;
787+ }
788+ case ELF::R_LARCH_GOT_PC_LO12:
789+ case ELF::R_LARCH_PCALA_LO12: {
790+ uint64_t TargetOffset = (Value + Addend) & 0xfff ;
791+ auto Instr = support::ulittle32_t::ref (TargetPtr);
792+ uint32_t Imm11_0 = TargetOffset << 10 ;
793+ Instr = (Instr & 0xffc003ff ) | Imm11_0;
794+ break ;
795+ }
796+ case ELF::R_LARCH_ABS_HI20: {
797+ uint64_t Target = Value + Addend;
798+ auto Instr = support::ulittle32_t::ref (TargetPtr);
799+ uint32_t Imm31_12 = extractBits (Target, /* Hi=*/ 31 , /* Lo=*/ 12 ) << 5 ;
800+ Instr = (Instr & 0xfe00001f ) | Imm31_12;
801+ break ;
802+ }
803+ case ELF::R_LARCH_ABS_LO12: {
804+ uint64_t Target = Value + Addend;
805+ auto Instr = support::ulittle32_t::ref (TargetPtr);
806+ uint32_t Imm11_0 = extractBits (Target, /* Hi=*/ 11 , /* Lo=*/ 0 ) << 10 ;
807+ Instr = (Instr & 0xffc003ff ) | Imm11_0;
808+ break ;
809+ }
810+ case ELF::R_LARCH_ABS64_LO20: {
811+ uint64_t Target = Value + Addend;
812+ auto Instr = support::ulittle32_t::ref (TargetPtr);
813+ uint32_t Imm51_32 = extractBits (Target, /* Hi=*/ 51 , /* Lo=*/ 32 ) << 5 ;
814+ Instr = (Instr & 0xfe00001f ) | Imm51_32;
815+ break ;
816+ }
817+ case ELF::R_LARCH_ABS64_HI12: {
818+ uint64_t Target = Value + Addend;
819+ auto Instr = support::ulittle32_t::ref (TargetPtr);
820+ uint32_t Imm63_52 = extractBits (Target, /* Hi=*/ 63 , /* Lo=*/ 52 ) << 10 ;
821+ Instr = (Instr & 0xffc003ff ) | Imm63_52;
822+ break ;
823+ }
824+ case ELF::R_LARCH_ADD32:
825+ support::ulittle32_t ::ref{TargetPtr} =
826+ (support::ulittle32_t ::ref{TargetPtr} +
827+ static_cast <uint32_t >(Value + Addend));
828+ break ;
829+ case ELF::R_LARCH_SUB32:
830+ support::ulittle32_t ::ref{TargetPtr} =
831+ (support::ulittle32_t ::ref{TargetPtr} -
832+ static_cast <uint32_t >(Value + Addend));
833+ break ;
834+ case ELF::R_LARCH_ADD64:
835+ support::ulittle64_t ::ref{TargetPtr} =
836+ (support::ulittle64_t ::ref{TargetPtr} + Value + Addend);
837+ break ;
838+ case ELF::R_LARCH_SUB64:
839+ support::ulittle64_t ::ref{TargetPtr} =
840+ (support::ulittle64_t ::ref{TargetPtr} - Value - Addend);
841+ break ;
842+ }
843+ }
844+
648845void RuntimeDyldELF::setMipsABI (const ObjectFile &Obj) {
649846 if (Arch == Triple::UnknownArch ||
650847 Triple::getArchTypePrefix (Arch) != " mips" ) {
@@ -1190,6 +1387,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
11901387 resolveARMRelocation (Section, Offset, (uint32_t )(Value & 0xffffffffL ), Type,
11911388 (uint32_t )(Addend & 0xffffffffL ));
11921389 break ;
1390+ case Triple::loongarch64:
1391+ resolveLoongArch64Relocation (Section, Offset, Value, Type, Addend);
1392+ break ;
11931393 case Triple::ppc: // Fall through.
11941394 case Triple::ppcle:
11951395 resolvePPC32Relocation (Section, Offset, Value, Type, Addend);
@@ -1515,6 +1715,17 @@ RuntimeDyldELF::processRelocationRef(
15151715 }
15161716 processSimpleRelocation (SectionID, Offset, RelType, Value);
15171717 }
1718+ } else if (Arch == Triple::loongarch64) {
1719+ if (RelType == ELF::R_LARCH_B26 && MemMgr.allowStubAllocation ()) {
1720+ resolveLoongArch64Branch (SectionID, Value, RelI, Stubs);
1721+ } else if (RelType == ELF::R_LARCH_GOT_PC_HI20 ||
1722+ RelType == ELF::R_LARCH_GOT_PC_LO12) {
1723+ uint64_t GOTOffset = findOrAllocGOTEntry (Value, ELF::R_LARCH_64);
1724+ resolveGOTOffsetRelocation (SectionID, Offset, GOTOffset + Addend,
1725+ RelType);
1726+ } else {
1727+ processSimpleRelocation (SectionID, Offset, RelType, Value);
1728+ }
15181729 } else if (IsMipsO32ABI) {
15191730 uint8_t *Placeholder = reinterpret_cast <uint8_t *>(
15201731 computePlaceholderAddress (SectionID, Offset));
@@ -2371,6 +2582,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
23712582 case Triple::x86_64:
23722583 case Triple::aarch64:
23732584 case Triple::aarch64_be:
2585+ case Triple::loongarch64:
23742586 case Triple::ppc64:
23752587 case Triple::ppc64le:
23762588 case Triple::systemz:
@@ -2683,6 +2895,10 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
26832895 return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE ||
26842896 RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC;
26852897
2898+ if (Arch == Triple::loongarch64)
2899+ return RelTy == ELF::R_LARCH_GOT_PC_HI20 ||
2900+ RelTy == ELF::R_LARCH_GOT_PC_LO12;
2901+
26862902 if (Arch == Triple::x86_64)
26872903 return RelTy == ELF::R_X86_64_GOTPCREL ||
26882904 RelTy == ELF::R_X86_64_GOTPCRELX ||
0 commit comments