@@ -61,6 +61,7 @@ enum Op {
61
61
AUIPC = 0x17 ,
62
62
JALR = 0x67 ,
63
63
LD = 0x3003 ,
64
+ LUI = 0x37 ,
64
65
LW = 0x2003 ,
65
66
SRLI = 0x5013 ,
66
67
SUB = 0x40000033 ,
@@ -73,6 +74,7 @@ enum Reg {
73
74
X_T0 = 5 ,
74
75
X_T1 = 6 ,
75
76
X_T2 = 7 ,
77
+ X_A0 = 10 ,
76
78
X_T3 = 28 ,
77
79
};
78
80
@@ -102,6 +104,26 @@ static uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
102
104
(extractBits (imm, 4 , 0 ) << 7 );
103
105
}
104
106
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
+
105
127
RISCV::RISCV () {
106
128
copyRel = R_RISCV_COPY;
107
129
pltRel = R_RISCV_JUMP_SLOT;
@@ -119,6 +141,7 @@ RISCV::RISCV() {
119
141
tlsGotRel = R_RISCV_TLS_TPREL32;
120
142
}
121
143
gotRel = symbolicRel;
144
+ tlsDescRel = R_RISCV_TLSDESC;
122
145
123
146
// .got[0] = _DYNAMIC
124
147
gotHeaderEntriesNum = 1 ;
@@ -187,6 +210,8 @@ int64_t RISCV::getImplicitAddend(const uint8_t *buf, RelType type) const {
187
210
case R_RISCV_JUMP_SLOT:
188
211
// These relocations are defined as not having an implicit addend.
189
212
return 0 ;
213
+ case R_RISCV_TLSDESC:
214
+ return config->is64 ? read64le (buf + 8 ) : read32le (buf + 4 );
190
215
}
191
216
}
192
217
@@ -295,6 +320,12 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
295
320
case R_RISCV_PCREL_LO12_I:
296
321
case R_RISCV_PCREL_LO12_S:
297
322
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;
298
329
case R_RISCV_TLS_GD_HI20:
299
330
return R_TLSGD_PC;
300
331
case R_RISCV_TLS_GOT_HI20:
@@ -419,6 +450,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
419
450
420
451
case R_RISCV_GOT_HI20:
421
452
case R_RISCV_PCREL_HI20:
453
+ case R_RISCV_TLSDESC_HI20:
422
454
case R_RISCV_TLS_GD_HI20:
423
455
case R_RISCV_TLS_GOT_HI20:
424
456
case R_RISCV_TPREL_HI20:
@@ -430,6 +462,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
430
462
}
431
463
432
464
case R_RISCV_PCREL_LO12_I:
465
+ case R_RISCV_TLSDESC_LOAD_LO12:
466
+ case R_RISCV_TLSDESC_ADD_LO12:
433
467
case R_RISCV_TPREL_LO12_I:
434
468
case R_RISCV_LO12_I: {
435
469
uint64_t hi = (val + 0x800 ) >> 12 ;
@@ -513,29 +547,113 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
513
547
break ;
514
548
515
549
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 ;
518
558
default :
519
559
llvm_unreachable (" unknown relocation" );
520
560
}
521
561
}
522
562
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
+
523
603
void RISCV::relocateAlloc (InputSectionBase &sec, uint8_t *buf) const {
524
604
uint64_t secAddr = sec.getOutputSection ()->addr ;
525
605
if (auto *s = dyn_cast<InputSection>(&sec))
526
606
secAddr += s->outSecOff ;
527
607
else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
528
608
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];
531
614
uint8_t *loc = buf + rel.offset ;
532
- const uint64_t val =
615
+ uint64_t val =
533
616
sec.getRelocTargetVA (sec.file , rel.type , rel.addend ,
534
617
secAddr + rel.offset , *rel.sym , rel.expr );
535
618
536
619
switch (rel.expr ) {
537
620
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;
538
629
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 be smaller than `val` to take
634
+ // into account of NOP instructions (in the absence of R_RISCV_RELAX)
635
+ // before AUIPC.
636
+ tlsdescVal = val + rel.offset ;
637
+ isToIe = true ;
638
+ tlsdescToIe (loc, rel, val);
639
+ continue ;
640
+ case R_RELAX_TLS_GD_TO_LE:
641
+ // See the comment in handleTlsRelocation. For TLSDESC=>IE,
642
+ // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToIe is
643
+ // true, this is actually TLSDESC=>IE optimization.
644
+ if (rel.type == R_RISCV_TLSDESC_HI20) {
645
+ tlsdescVal = val;
646
+ isToIe = false ;
647
+ } else {
648
+ if (isToIe && rel.type == R_RISCV_TLSDESC_ADD_LO12)
649
+ tlsdescVal -= rel.offset ;
650
+ val = tlsdescVal;
651
+ }
652
+ if (isToIe)
653
+ tlsdescToIe (loc, rel, val);
654
+ else
655
+ tlsdescToLe (loc, rel, val);
656
+ continue ;
539
657
case R_RISCV_LEB128:
540
658
if (i + 1 < size) {
541
659
const Relocation &rel1 = sec.relocs ()[i + 1 ];
@@ -554,32 +672,12 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
554
672
" : R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128" );
555
673
return ;
556
674
default :
557
- relocate (loc, rel, val);
558
675
break ;
559
676
}
677
+ relocate (loc, rel, val);
560
678
}
561
679
}
562
680
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
-
583
681
static void initSymbolAnchors () {
584
682
SmallVector<InputSection *, 0 > storage;
585
683
for (OutputSection *osec : outputSections) {
@@ -762,6 +860,14 @@ static bool relax(InputSection &sec) {
762
860
sec.relocs ()[i + 1 ].type == R_RISCV_RELAX)
763
861
relaxHi20Lo12 (sec, i, loc, r, remove );
764
862
break ;
863
+ case R_RISCV_TLSDESC_HI20:
864
+ case R_RISCV_TLSDESC_LOAD_LO12:
865
+ // For LE or IE optimization, AUIPC and L[DW] are converted to a removable
866
+ // NOP.
867
+ if (r.expr != R_TLSDESC_PC && i + 1 != sec.relocs ().size () &&
868
+ sec.relocs ()[i + 1 ].type == R_RISCV_RELAX)
869
+ remove = 4 ;
870
+ break ;
765
871
}
766
872
767
873
// For all anchors whose offsets are <= r.offset, they are preceded by
0 commit comments