@@ -61,6 +61,7 @@ enum Op {
6161 AUIPC = 0x17 ,
6262 JALR = 0x67 ,
6363 LD = 0x3003 ,
64+ LUI = 0x37 ,
6465 LW = 0x2003 ,
6566 SRLI = 0x5013 ,
6667 SUB = 0x40000033 ,
@@ -73,6 +74,7 @@ enum Reg {
7374 X_T0 = 5 ,
7475 X_T1 = 6 ,
7576 X_T2 = 7 ,
77+ X_A0 = 10 ,
7678 X_T3 = 28 ,
7779};
7880
@@ -102,6 +104,26 @@ static uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
102104 (extractBits (imm, 4 , 0 ) << 7 );
103105}
104106
107+ namespace {
108+ struct SymbolAnchor {
109+ uint64_t offset;
110+ Defined *d;
111+ bool end; // true for the anchor of st_value+st_size
112+ };
113+ } // namespace
114+
115+ struct elf ::RISCVRelaxAux {
116+ // This records symbol start and end offsets which will be adjusted according
117+ // to the nearest relocDeltas element.
118+ SmallVector<SymbolAnchor, 0 > anchors;
119+ // For relocations[i], the actual offset is r_offset - (i ? relocDeltas[i-1] :
120+ // 0).
121+ std::unique_ptr<uint32_t []> relocDeltas;
122+ // For relocations[i], the actual type is relocTypes[i].
123+ std::unique_ptr<RelType[]> relocTypes;
124+ SmallVector<uint32_t , 0 > writes;
125+ };
126+
105127RISCV::RISCV () {
106128 copyRel = R_RISCV_COPY;
107129 pltRel = R_RISCV_JUMP_SLOT;
@@ -119,6 +141,7 @@ RISCV::RISCV() {
119141 tlsGotRel = R_RISCV_TLS_TPREL32;
120142 }
121143 gotRel = symbolicRel;
144+ tlsDescRel = R_RISCV_TLSDESC;
122145
123146 // .got[0] = _DYNAMIC
124147 gotHeaderEntriesNum = 1 ;
@@ -187,6 +210,8 @@ int64_t RISCV::getImplicitAddend(const uint8_t *buf, RelType type) const {
187210 case R_RISCV_JUMP_SLOT:
188211 // These relocations are defined as not having an implicit addend.
189212 return 0 ;
213+ case R_RISCV_TLSDESC:
214+ return config->is64 ? read64le (buf + 8 ) : read32le (buf + 4 );
190215 }
191216}
192217
@@ -295,6 +320,12 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
295320 case R_RISCV_PCREL_LO12_I:
296321 case R_RISCV_PCREL_LO12_S:
297322 return R_RISCV_PC_INDIRECT;
323+ case R_RISCV_TLSDESC_HI20:
324+ case R_RISCV_TLSDESC_LOAD_LO12:
325+ case R_RISCV_TLSDESC_ADD_LO12:
326+ return R_TLSDESC_PC;
327+ case R_RISCV_TLSDESC_CALL:
328+ return R_TLSDESC_CALL;
298329 case R_RISCV_TLS_GD_HI20:
299330 return R_TLSGD_PC;
300331 case R_RISCV_TLS_GOT_HI20:
@@ -419,6 +450,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
419450
420451 case R_RISCV_GOT_HI20:
421452 case R_RISCV_PCREL_HI20:
453+ case R_RISCV_TLSDESC_HI20:
422454 case R_RISCV_TLS_GD_HI20:
423455 case R_RISCV_TLS_GOT_HI20:
424456 case R_RISCV_TPREL_HI20:
@@ -430,6 +462,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
430462 }
431463
432464 case R_RISCV_PCREL_LO12_I:
465+ case R_RISCV_TLSDESC_LOAD_LO12:
466+ case R_RISCV_TLSDESC_ADD_LO12:
433467 case R_RISCV_TPREL_LO12_I:
434468 case R_RISCV_LO12_I: {
435469 uint64_t hi = (val + 0x800 ) >> 12 ;
@@ -513,29 +547,112 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
513547 break ;
514548
515549 case R_RISCV_RELAX:
516- return ; // Ignored (for now)
517-
550+ return ;
551+ case R_RISCV_TLSDESC:
552+ // The addend is stored in the second word.
553+ if (config->is64 )
554+ write64le (loc + 8 , val);
555+ else
556+ write32le (loc + 4 , val);
557+ break ;
518558 default :
519559 llvm_unreachable (" unknown relocation" );
520560 }
521561}
522562
563+ static void tlsdescToIe (uint8_t *loc, const Relocation &rel, uint64_t val) {
564+ switch (rel.type ) {
565+ case R_RISCV_TLSDESC_HI20:
566+ case R_RISCV_TLSDESC_LOAD_LO12:
567+ write32le (loc, 0x00000013 ); // nop
568+ return ;
569+ case R_RISCV_TLSDESC_ADD_LO12:
570+ write32le (loc, utype (AUIPC, X_A0, hi20 (val))); // auipc a0,<hi20>
571+ return ;
572+ case R_RISCV_TLSDESC_CALL:
573+ if (config->is64 )
574+ write32le (loc, itype (LD, X_A0, X_A0, lo12 (val))); // ld a0,<lo12>(a0)
575+ else
576+ write32le (loc, itype (LW, X_A0, X_A0, lo12 (val))); // lw a0,<lo12>(a0)
577+ return ;
578+ default :
579+ llvm_unreachable (" unsupported relocation for TLSDESC to IE relaxation" );
580+ }
581+ }
582+
583+ static void tlsdescToLe (uint8_t *loc, const Relocation &rel, uint64_t val) {
584+ switch (rel.type ) {
585+ case R_RISCV_TLSDESC_HI20:
586+ case R_RISCV_TLSDESC_LOAD_LO12:
587+ write32le (loc, 0x00000013 ); // nop
588+ return ;
589+ case R_RISCV_TLSDESC_ADD_LO12:
590+ write32le (loc, utype (LUI, X_A0, hi20 (val))); // lui a0,<hi20>
591+ return ;
592+ case R_RISCV_TLSDESC_CALL:
593+ if (isInt<12 >(val))
594+ write32le (loc, itype (ADDI, X_A0, 0 , val)); // addi a0,zero,<lo12>
595+ else
596+ write32le (loc, itype (ADDI, X_A0, X_A0, lo12 (val))); // addi a0,a0,<lo12>
597+ return ;
598+ default :
599+ llvm_unreachable (" unsupported relocation for TLSDESC to LE relaxation" );
600+ }
601+ }
602+
523603void RISCV::relocateAlloc (InputSectionBase &sec, uint8_t *buf) const {
524604 uint64_t secAddr = sec.getOutputSection ()->addr ;
525605 if (auto *s = dyn_cast<InputSection>(&sec))
526606 secAddr += s->outSecOff ;
527607 else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
528608 secAddr += ehIn->getParent ()->outSecOff ;
529- for (size_t i = 0 , size = sec.relocs ().size (); i != size; ++i) {
530- const Relocation &rel = sec.relocs ()[i];
609+ uint64_t tlsdescVal = 0 ;
610+ bool isToIe = true ;
611+ const ArrayRef<Relocation> relocs = sec.relocs ();
612+ for (size_t i = 0 , size = relocs.size (); i != size; ++i) {
613+ const Relocation &rel = relocs[i];
531614 uint8_t *loc = buf + rel.offset ;
532- const uint64_t val =
615+ uint64_t val =
533616 sec.getRelocTargetVA (sec.file , rel.type , rel.addend ,
534617 secAddr + rel.offset , *rel.sym , rel.expr );
535618
536619 switch (rel.expr ) {
537620 case R_RELAX_HINT:
621+ continue ;
622+ case R_TLSDESC_PC:
623+ // For R_RISCV_TLSDESC_HI20, store &got(sym)-PC to be used by the
624+ // following two instructions L[DW] and ADDI.
625+ if (rel.type == R_RISCV_TLSDESC_HI20)
626+ tlsdescVal = val;
627+ else
628+ val = tlsdescVal;
538629 break ;
630+ case R_RELAX_TLS_GD_TO_IE:
631+ // Only R_RISCV_TLSDESC_HI20 reaches here. tlsdescVal will be finalized
632+ // after we see R_RISCV_TLSDESC_ADD_LO12 in the R_RELAX_TLS_GD_TO_LE case.
633+ // The net effect is that tlsdescVal will decrease to take into account of
634+ // NOP instructions (in the absence of R_RISCV_RELAX) before AUIPC.
635+ tlsdescVal = val + rel.offset ;
636+ isToIe = true ;
637+ tlsdescToIe (loc, rel, val);
638+ continue ;
639+ case R_RELAX_TLS_GD_TO_LE:
640+ // See the comment in handleTlsRelocation. For TLSDESC=>IE,
641+ // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToIe is
642+ // true, this is actually TLSDESC=>IE optimization.
643+ if (rel.type == R_RISCV_TLSDESC_HI20) {
644+ tlsdescVal = val;
645+ isToIe = false ;
646+ } else {
647+ if (isToIe && rel.type == R_RISCV_TLSDESC_ADD_LO12)
648+ tlsdescVal -= rel.offset ;
649+ val = tlsdescVal;
650+ }
651+ if (isToIe)
652+ tlsdescToIe (loc, rel, val);
653+ else
654+ tlsdescToLe (loc, rel, val);
655+ continue ;
539656 case R_RISCV_LEB128:
540657 if (i + 1 < size) {
541658 const Relocation &rel1 = sec.relocs ()[i + 1 ];
@@ -554,32 +671,12 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
554671 " : R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128" );
555672 return ;
556673 default :
557- relocate (loc, rel, val);
558674 break ;
559675 }
676+ relocate (loc, rel, val);
560677 }
561678}
562679
563- namespace {
564- struct SymbolAnchor {
565- uint64_t offset;
566- Defined *d;
567- bool end; // true for the anchor of st_value+st_size
568- };
569- } // namespace
570-
571- struct elf ::RISCVRelaxAux {
572- // This records symbol start and end offsets which will be adjusted according
573- // to the nearest relocDeltas element.
574- SmallVector<SymbolAnchor, 0 > anchors;
575- // For relocations[i], the actual offset is r_offset - (i ? relocDeltas[i-1] :
576- // 0).
577- std::unique_ptr<uint32_t []> relocDeltas;
578- // For relocations[i], the actual type is relocTypes[i].
579- std::unique_ptr<RelType[]> relocTypes;
580- SmallVector<uint32_t , 0 > writes;
581- };
582-
583680static void initSymbolAnchors () {
584681 SmallVector<InputSection *, 0 > storage;
585682 for (OutputSection *osec : outputSections) {
@@ -762,6 +859,14 @@ static bool relax(InputSection &sec) {
762859 sec.relocs ()[i + 1 ].type == R_RISCV_RELAX)
763860 relaxHi20Lo12 (sec, i, loc, r, remove);
764861 break ;
862+ case R_RISCV_TLSDESC_HI20:
863+ case R_RISCV_TLSDESC_LOAD_LO12:
864+ // For LE or IE optimization, AUIPC and L[DW] are converted to a removable
865+ // NOP.
866+ if (r.expr != R_TLSDESC_PC && i + 1 != sec.relocs ().size () &&
867+ sec.relocs ()[i + 1 ].type == R_RISCV_RELAX)
868+ remove = 4 ;
869+ break ;
765870 }
766871
767872 // For all anchors whose offsets are <= r.offset, they are preceded by
0 commit comments