@@ -645,6 +645,206 @@ 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+
679+ if (resolveLoongArch64ShortBranch (SectionID, RelI, Value))
680+ return ;
681+
682+ SectionEntry &Section = Sections[SectionID];
683+ uint64_t Offset = RelI->getOffset ();
684+ unsigned RelType = RelI->getType ();
685+ // Look for an existing stub.
686+ StubMap::const_iterator i = Stubs.find (Value);
687+ if (i != Stubs.end ()) {
688+ resolveRelocation (Section, Offset,
689+ (uint64_t )Section.getAddressWithOffset (i->second ),
690+ RelType, 0 );
691+ LLVM_DEBUG (dbgs () << " Stub function found\n " );
692+ return ;
693+ }
694+ // Create a new stub function.
695+ LLVM_DEBUG (dbgs () << " Create a new stub function\n " );
696+ Stubs[Value] = Section.getStubOffset ();
697+ uint8_t *StubTargetAddr =
698+ createStubFunction (Section.getAddressWithOffset (Section.getStubOffset ()));
699+ RelocationEntry LU12I_W (SectionID, StubTargetAddr - Section.getAddress (),
700+ ELF::R_LARCH_ABS_HI20, Value.Addend );
701+ RelocationEntry ORI (SectionID, StubTargetAddr - Section.getAddress () + 4 ,
702+ ELF::R_LARCH_ABS_LO12, Value.Addend );
703+ RelocationEntry LU32I_D (SectionID, StubTargetAddr - Section.getAddress () + 8 ,
704+ ELF::R_LARCH_ABS64_LO20, Value.Addend );
705+ RelocationEntry LU52I_D (SectionID, StubTargetAddr - Section.getAddress () + 12 ,
706+ ELF::R_LARCH_ABS64_HI12, Value.Addend );
707+ if (Value.SymbolName ) {
708+ addRelocationForSymbol (LU12I_W, Value.SymbolName );
709+ addRelocationForSymbol (ORI, Value.SymbolName );
710+ addRelocationForSymbol (LU32I_D, Value.SymbolName );
711+ addRelocationForSymbol (LU52I_D, Value.SymbolName );
712+ } else {
713+ addRelocationForSection (LU12I_W, Value.SectionID );
714+ addRelocationForSection (ORI, Value.SectionID );
715+ addRelocationForSection (LU32I_D, Value.SectionID );
716+
717+ addRelocationForSection (LU52I_D, Value.SectionID );
718+ }
719+ resolveRelocation (Section, Offset,
720+ reinterpret_cast <uint64_t >(
721+ Section.getAddressWithOffset (Section.getStubOffset ())),
722+ RelType, 0 );
723+ Section.advanceStubOffset (getMaxStubSize ());
724+ }
725+
726+ // Returns extract bits Val[Hi:Lo].
727+ static inline uint32_t extractBits (uint64_t Val, uint32_t Hi, uint32_t Lo) {
728+ return Hi == 63 ? Val >> Lo : (Val & (((1ULL << (Hi + 1 )) - 1 ))) >> Lo;
729+ }
730+
731+ void RuntimeDyldELF::resolveLoongArch64Relocation (const SectionEntry &Section,
732+ uint64_t Offset,
733+ uint64_t Value, uint32_t Type,
734+ int64_t Addend) {
735+ auto *TargetPtr = Section.getAddressWithOffset (Offset);
736+ uint64_t FinalAddress = Section.getLoadAddressWithOffset (Offset);
737+
738+ LLVM_DEBUG (dbgs () << " resolveLoongArch64Relocation, LocalAddress: 0x"
739+ << format (" %llx" , Section.getAddressWithOffset (Offset))
740+ << " FinalAddress: 0x" << format (" %llx" , FinalAddress)
741+ << " Value: 0x" << format (" %llx" , Value) << " Type: 0x"
742+ << format (" %x" , Type) << " Addend: 0x"
743+ << format (" %llx" , Addend) << " \n " );
744+
745+ switch (Type) {
746+ default :
747+ report_fatal_error (" Relocation type not implemented yet!" );
748+ break ;
749+ case ELF::R_LARCH_32:
750+ support::ulittle32_t ::ref{TargetPtr} =
751+ static_cast <uint32_t >(Value + Addend);
752+ break ;
753+ case ELF::R_LARCH_64:
754+ support::ulittle64_t ::ref{TargetPtr} = Value + Addend;
755+ break ;
756+ case ELF::R_LARCH_32_PCREL:
757+ support::ulittle32_t ::ref{TargetPtr} =
758+ static_cast <uint32_t >(Value + Addend - FinalAddress);
759+ break ;
760+ case ELF::R_LARCH_B26: {
761+ uint64_t B26 = (Value + Addend - FinalAddress) >> 2 ;
762+ auto Instr = support::ulittle32_t::ref (TargetPtr);
763+ uint32_t Imm15_0 = extractBits (B26, /* Hi=*/ 15 , /* Lo=*/ 0 ) << 10 ;
764+ uint32_t Imm25_16 = extractBits (B26, /* Hi=*/ 25 , /* Lo=*/ 16 );
765+ Instr = (Instr & 0xfc000000 ) | Imm15_0 | Imm25_16;
766+ break ;
767+ }
768+ case ELF::R_LARCH_CALL36: {
769+ uint64_t Call36 = (Value + Addend - FinalAddress) >> 2 ;
770+ auto Pcaddu18i = support::ulittle32_t::ref (TargetPtr);
771+ uint32_t Imm35_16 =
772+ extractBits ((Call36 + (1UL << 15 )), /* Hi=*/ 35 , /* Lo=*/ 16 ) << 5 ;
773+ Pcaddu18i = (Pcaddu18i & 0xfe00001f ) | Imm35_16;
774+ auto Jirl = support::ulittle32_t::ref (TargetPtr + 4 );
775+ uint32_t Imm15_0 = extractBits (Call36, /* Hi=*/ 15 , /* Lo=*/ 0 ) << 10 ;
776+ Jirl = (Jirl & 0xfc0003ff ) | Imm15_0;
777+ break ;
778+ }
779+ case ELF::R_LARCH_GOT_PC_HI20:
780+ case ELF::R_LARCH_PCALA_HI20: {
781+ uint64_t Target = Value + Addend;
782+ uint64_t TargetPage =
783+ (Target + (Target & 0x800 )) & ~static_cast <uint64_t >(0xfff );
784+ uint64_t PCPage = FinalAddress & ~static_cast <uint64_t >(0xfff );
785+ int64_t PageDelta = TargetPage - PCPage;
786+ auto Instr = support::ulittle32_t::ref (TargetPtr);
787+ uint32_t Imm31_12 = extractBits (PageDelta, /* Hi=*/ 31 , /* Lo=*/ 12 ) << 5 ;
788+ Instr = (Instr & 0xfe00001f ) | Imm31_12;
789+ break ;
790+ }
791+ case ELF::R_LARCH_GOT_PC_LO12:
792+ case ELF::R_LARCH_PCALA_LO12: {
793+ uint64_t TargetOffset = (Value + Addend) & 0xfff ;
794+ auto Instr = support::ulittle32_t::ref (TargetPtr);
795+ uint32_t Imm11_0 = TargetOffset << 10 ;
796+ Instr = (Instr & 0xffc003ff ) | Imm11_0;
797+ break ;
798+ }
799+ case ELF::R_LARCH_ABS_HI20: {
800+ uint64_t Target = Value + Addend;
801+ auto Instr = support::ulittle32_t::ref (TargetPtr);
802+ uint32_t Imm31_12 = extractBits (Target, /* Hi=*/ 31 , /* Lo=*/ 12 ) << 5 ;
803+ Instr = (Instr & 0xfe00001f ) | Imm31_12;
804+ break ;
805+ }
806+ case ELF::R_LARCH_ABS_LO12: {
807+ uint64_t Target = Value + Addend;
808+ auto Instr = support::ulittle32_t::ref (TargetPtr);
809+ uint32_t Imm11_0 = extractBits (Target, /* Hi=*/ 11 , /* Lo=*/ 0 ) << 10 ;
810+ Instr = (Instr & 0xffc003ff ) | Imm11_0;
811+ break ;
812+ }
813+ case ELF::R_LARCH_ABS64_LO20: {
814+ uint64_t Target = Value + Addend;
815+ auto Instr = support::ulittle32_t::ref (TargetPtr);
816+ uint32_t Imm51_32 = extractBits (Target, /* Hi=*/ 51 , /* Lo=*/ 32 ) << 5 ;
817+ Instr = (Instr & 0xfe00001f ) | Imm51_32;
818+ break ;
819+ }
820+ case ELF::R_LARCH_ABS64_HI12: {
821+ uint64_t Target = Value + Addend;
822+ auto Instr = support::ulittle32_t::ref (TargetPtr);
823+ uint32_t Imm63_52 = extractBits (Target, /* Hi=*/ 63 , /* Lo=*/ 52 ) << 10 ;
824+ Instr = (Instr & 0xffc003ff ) | Imm63_52;
825+ break ;
826+ }
827+ case ELF::R_LARCH_ADD32:
828+ support::ulittle32_t ::ref{TargetPtr} =
829+ (support::ulittle32_t ::ref{TargetPtr} +
830+ static_cast <uint32_t >(Value + Addend));
831+ break ;
832+ case ELF::R_LARCH_SUB32:
833+ support::ulittle32_t ::ref{TargetPtr} =
834+ (support::ulittle32_t ::ref{TargetPtr} -
835+ static_cast <uint32_t >(Value + Addend));
836+ break ;
837+ case ELF::R_LARCH_ADD64:
838+ support::ulittle64_t ::ref{TargetPtr} =
839+ (support::ulittle64_t ::ref{TargetPtr} + Value + Addend);
840+ break ;
841+ case ELF::R_LARCH_SUB64:
842+ support::ulittle64_t ::ref{TargetPtr} =
843+ (support::ulittle64_t ::ref{TargetPtr} - Value - Addend);
844+ break ;
845+ }
846+ }
847+
648848void RuntimeDyldELF::setMipsABI (const ObjectFile &Obj) {
649849 if (Arch == Triple::UnknownArch ||
650850 Triple::getArchTypePrefix (Arch) != " mips" ) {
@@ -1190,6 +1390,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
11901390 resolveARMRelocation (Section, Offset, (uint32_t )(Value & 0xffffffffL ), Type,
11911391 (uint32_t )(Addend & 0xffffffffL ));
11921392 break ;
1393+ case Triple::loongarch64:
1394+ resolveLoongArch64Relocation (Section, Offset, Value, Type, Addend);
1395+ break ;
11931396 case Triple::ppc: // Fall through.
11941397 case Triple::ppcle:
11951398 resolvePPC32Relocation (Section, Offset, Value, Type, Addend);
@@ -1515,6 +1718,17 @@ RuntimeDyldELF::processRelocationRef(
15151718 }
15161719 processSimpleRelocation (SectionID, Offset, RelType, Value);
15171720 }
1721+ } else if (Arch == Triple::loongarch64) {
1722+ if (RelType == ELF::R_LARCH_B26 && MemMgr.allowStubAllocation ()) {
1723+ resolveLoongArch64Branch (SectionID, Value, RelI, Stubs);
1724+ } else if (RelType == ELF::R_LARCH_GOT_PC_HI20 ||
1725+ RelType == ELF::R_LARCH_GOT_PC_LO12) {
1726+ uint64_t GOTOffset = findOrAllocGOTEntry (Value, ELF::R_LARCH_64);
1727+ resolveGOTOffsetRelocation (SectionID, Offset, GOTOffset + Addend,
1728+ RelType);
1729+ } else {
1730+ processSimpleRelocation (SectionID, Offset, RelType, Value);
1731+ }
15181732 } else if (IsMipsO32ABI) {
15191733 uint8_t *Placeholder = reinterpret_cast <uint8_t *>(
15201734 computePlaceholderAddress (SectionID, Offset));
@@ -2371,6 +2585,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
23712585 case Triple::x86_64:
23722586 case Triple::aarch64:
23732587 case Triple::aarch64_be:
2588+ case Triple::loongarch64:
23742589 case Triple::ppc64:
23752590 case Triple::ppc64le:
23762591 case Triple::systemz:
@@ -2683,6 +2898,10 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
26832898 return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE ||
26842899 RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC;
26852900
2901+ if (Arch == Triple::loongarch64)
2902+ return RelTy == ELF::R_LARCH_GOT_PC_HI20 ||
2903+ RelTy == ELF::R_LARCH_GOT_PC_LO12;
2904+
26862905 if (Arch == Triple::x86_64)
26872906 return RelTy == ELF::R_X86_64_GOTPCREL ||
26882907 RelTy == ELF::R_X86_64_GOTPCRELX ||
0 commit comments