@@ -645,6 +645,206 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
645
645
}
646
646
}
647
647
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
+
648
848
void RuntimeDyldELF::setMipsABI (const ObjectFile &Obj) {
649
849
if (Arch == Triple::UnknownArch ||
650
850
Triple::getArchTypePrefix (Arch) != " mips" ) {
@@ -1190,6 +1390,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
1190
1390
resolveARMRelocation (Section, Offset, (uint32_t )(Value & 0xffffffffL ), Type,
1191
1391
(uint32_t )(Addend & 0xffffffffL ));
1192
1392
break ;
1393
+ case Triple::loongarch64:
1394
+ resolveLoongArch64Relocation (Section, Offset, Value, Type, Addend);
1395
+ break ;
1193
1396
case Triple::ppc: // Fall through.
1194
1397
case Triple::ppcle:
1195
1398
resolvePPC32Relocation (Section, Offset, Value, Type, Addend);
@@ -1515,6 +1718,17 @@ RuntimeDyldELF::processRelocationRef(
1515
1718
}
1516
1719
processSimpleRelocation (SectionID, Offset, RelType, Value);
1517
1720
}
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
+ }
1518
1732
} else if (IsMipsO32ABI) {
1519
1733
uint8_t *Placeholder = reinterpret_cast <uint8_t *>(
1520
1734
computePlaceholderAddress (SectionID, Offset));
@@ -2371,6 +2585,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
2371
2585
case Triple::x86_64:
2372
2586
case Triple::aarch64:
2373
2587
case Triple::aarch64_be:
2588
+ case Triple::loongarch64:
2374
2589
case Triple::ppc64:
2375
2590
case Triple::ppc64le:
2376
2591
case Triple::systemz:
@@ -2683,6 +2898,10 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
2683
2898
return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE ||
2684
2899
RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC;
2685
2900
2901
+ if (Arch == Triple::loongarch64)
2902
+ return RelTy == ELF::R_LARCH_GOT_PC_HI20 ||
2903
+ RelTy == ELF::R_LARCH_GOT_PC_LO12;
2904
+
2686
2905
if (Arch == Triple::x86_64)
2687
2906
return RelTy == ELF::R_X86_64_GOTPCREL ||
2688
2907
RelTy == ELF::R_X86_64_GOTPCRELX ||
0 commit comments