Skip to content

Commit 37e3966

Browse files
committed
[ELF] Make ThunkCreator take ownership of thunks
This removes many SpecificAlloc instantiations and makes my lld (x86-64 Release+Assertions) smaller by ~36k.
1 parent a520324 commit 37e3966

File tree

5 files changed

+79
-63
lines changed

5 files changed

+79
-63
lines changed

lld/ELF/Relocations.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,10 @@ static void forEachInputSectionDescription(
19071907
}
19081908
}
19091909

1910+
ThunkCreator::ThunkCreator(Ctx &ctx) : ctx(ctx) {}
1911+
1912+
ThunkCreator::~ThunkCreator() {}
1913+
19101914
// Thunk Implementation
19111915
//
19121916
// Thunks (sometimes called stubs, veneers or branch islands) are small pieces
@@ -2212,7 +2216,7 @@ static bool isThunkSectionCompatible(InputSection *source,
22122216

22132217
std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
22142218
Relocation &rel, uint64_t src) {
2215-
std::vector<Thunk *> *thunkVec = nullptr;
2219+
SmallVector<std::unique_ptr<Thunk>, 0> *thunkVec = nullptr;
22162220
// Arm and Thumb have a PC Bias of 8 and 4 respectively, this is cancelled
22172221
// out in the relocation addend. We compensate for the PC bias so that
22182222
// an Arm and Thumb relocation to the same destination get the same keyAddend,
@@ -2233,17 +2237,16 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
22332237
thunkVec = &thunkedSymbols[{rel.sym, keyAddend}];
22342238

22352239
// Check existing Thunks for Sym to see if they can be reused
2236-
for (Thunk *t : *thunkVec)
2240+
for (auto &t : *thunkVec)
22372241
if (isThunkSectionCompatible(isec, t->getThunkTargetSym()->section) &&
22382242
t->isCompatibleWith(*isec, rel) &&
22392243
ctx.target->inBranchRange(rel.type, src,
22402244
t->getThunkTargetSym()->getVA(ctx, -pcBias)))
2241-
return std::make_pair(t, false);
2245+
return std::make_pair(t.get(), false);
22422246

22432247
// No existing compatible Thunk in range, create a new one
2244-
Thunk *t = addThunk(ctx, *isec, rel);
2245-
thunkVec->push_back(t);
2246-
return std::make_pair(t, true);
2248+
thunkVec->push_back(addThunk(ctx, *isec, rel));
2249+
return std::make_pair(thunkVec->back().get(), true);
22472250
}
22482251

22492252
std::pair<Thunk *, bool> ThunkCreator::getSyntheticLandingPad(Defined &d,
@@ -2252,7 +2255,7 @@ std::pair<Thunk *, bool> ThunkCreator::getSyntheticLandingPad(Defined &d,
22522255
{{d.section, d.value}, a}, nullptr);
22532256
if (isNew)
22542257
it->second = addLandingPadThunk(ctx, d, a);
2255-
return {it->second, isNew};
2258+
return {it->second.get(), isNew};
22562259
}
22572260

22582261
// Return true if the relocation target is an in range Thunk.

lld/ELF/Relocations.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ class InputSectionDescription;
163163

164164
class ThunkCreator {
165165
public:
166-
ThunkCreator(Ctx &ctx) : ctx(ctx) {}
166+
// Thunk may be incomplete. Avoid inline ctor/dtor.
167+
ThunkCreator(Ctx &ctx);
168+
~ThunkCreator();
167169
// Return true if Thunks have been added to OutputSections
168170
bool createThunks(uint32_t pass, ArrayRef<OutputSection *> outputSections);
169171

@@ -199,9 +201,10 @@ class ThunkCreator {
199201
// original addend, so we cannot fold offset + addend. A nested pair is used
200202
// because DenseMapInfo is not specialized for std::tuple.
201203
llvm::DenseMap<std::pair<std::pair<SectionBase *, uint64_t>, int64_t>,
202-
std::vector<Thunk *>>
204+
SmallVector<std::unique_ptr<Thunk>, 0>>
203205
thunkedSymbolsBySectionAndAddend;
204-
llvm::DenseMap<std::pair<Symbol *, int64_t>, std::vector<Thunk *>>
206+
llvm::DenseMap<std::pair<Symbol *, int64_t>,
207+
SmallVector<std::unique_ptr<Thunk>, 0>>
205208
thunkedSymbols;
206209

207210
// Find a Thunk from the Thunks symbol definition, we can use this to find
@@ -220,7 +223,7 @@ class ThunkCreator {
220223
// to be reached via thunks that use indirect branches. A destination
221224
// needs at most one landing pad as that can be reused by all callers.
222225
llvm::DenseMap<std::pair<std::pair<SectionBase *, uint64_t>, int64_t>,
223-
Thunk *>
226+
std::unique_ptr<Thunk>>
224227
landingPadsBySectionAndAddend;
225228

226229
// All the nonLandingPad thunks that have been created, in order of creation.

lld/ELF/Thunks.cpp

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,15 +1372,16 @@ Thunk::Thunk(Ctx &ctx, Symbol &d, int64_t a)
13721372

13731373
Thunk::~Thunk() = default;
13741374

1375-
static Thunk *addThunkAArch64(Ctx &ctx, RelType type, Symbol &s, int64_t a) {
1375+
static std::unique_ptr<Thunk> addThunkAArch64(Ctx &ctx, RelType type, Symbol &s,
1376+
int64_t a) {
13761377
assert(is_contained({R_AARCH64_CALL26, R_AARCH64_JUMP26, R_AARCH64_PLT32},
13771378
type));
13781379
bool mayNeedLandingPad =
13791380
(ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) &&
13801381
!isAArch64BTILandingPad(ctx, s, a);
13811382
if (ctx.arg.picThunk)
1382-
return make<AArch64ADRPThunk>(ctx, s, a, mayNeedLandingPad);
1383-
return make<AArch64ABSLongThunk>(ctx, s, a, mayNeedLandingPad);
1383+
return std::make_unique<AArch64ADRPThunk>(ctx, s, a, mayNeedLandingPad);
1384+
return std::make_unique<AArch64ABSLongThunk>(ctx, s, a, mayNeedLandingPad);
13841385
}
13851386

13861387
// Creates a thunk for long branches or Thumb-ARM interworking.
@@ -1391,7 +1392,8 @@ static Thunk *addThunkAArch64(Ctx &ctx, RelType type, Symbol &s, int64_t a) {
13911392
//
13921393
// TODO: use B for short Thumb->Arm thunks instead of LDR (this doesn't work for
13931394
// Arm->Thumb, as in Arm state no BX PC trick; it doesn't switch state).
1394-
static Thunk *addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s, int64_t a) {
1395+
static std::unique_ptr<Thunk> addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s,
1396+
int64_t a) {
13951397
bool thumb_target = s.getVA(ctx, a) & 1;
13961398

13971399
switch (reloc) {
@@ -1401,21 +1403,21 @@ static Thunk *addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s, int64_t a) {
14011403
case R_ARM_CALL:
14021404
if (ctx.arg.picThunk) {
14031405
if (thumb_target)
1404-
return make<ARMV4PILongBXThunk>(ctx, s, a);
1405-
return make<ARMV4PILongThunk>(ctx, s, a);
1406+
return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a);
1407+
return std::make_unique<ARMV4PILongThunk>(ctx, s, a);
14061408
}
14071409
if (thumb_target)
1408-
return make<ARMV4ABSLongBXThunk>(ctx, s, a);
1409-
return make<ARMV5LongLdrPcThunk>(ctx, s, a);
1410+
return std::make_unique<ARMV4ABSLongBXThunk>(ctx, s, a);
1411+
return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a);
14101412
case R_ARM_THM_CALL:
14111413
if (ctx.arg.picThunk) {
14121414
if (thumb_target)
1413-
return make<ThumbV4PILongThunk>(ctx, s, a);
1414-
return make<ThumbV4PILongBXThunk>(ctx, s, a);
1415+
return std::make_unique<ThumbV4PILongThunk>(ctx, s, a);
1416+
return std::make_unique<ThumbV4PILongBXThunk>(ctx, s, a);
14151417
}
14161418
if (thumb_target)
1417-
return make<ThumbV4ABSLongThunk>(ctx, s, a);
1418-
return make<ThumbV4ABSLongBXThunk>(ctx, s, a);
1419+
return std::make_unique<ThumbV4ABSLongThunk>(ctx, s, a);
1420+
return std::make_unique<ThumbV4ABSLongBXThunk>(ctx, s, a);
14191421
}
14201422
Fatal(ctx) << "relocation " << reloc << " to " << &s
14211423
<< " not supported for Armv4 or Armv4T target";
@@ -1427,16 +1429,17 @@ static Thunk *addThunkArmv4(Ctx &ctx, RelType reloc, Symbol &s, int64_t a) {
14271429
// - MOVT and MOVW instructions cannot be used
14281430
// - Only Thumb relocation that can generate a Thunk is a BL, this can always
14291431
// be transformed into a BLX
1430-
static Thunk *addThunkArmv5v6(Ctx &ctx, RelType reloc, Symbol &s, int64_t a) {
1432+
static std::unique_ptr<Thunk> addThunkArmv5v6(Ctx &ctx, RelType reloc,
1433+
Symbol &s, int64_t a) {
14311434
switch (reloc) {
14321435
case R_ARM_PC24:
14331436
case R_ARM_PLT32:
14341437
case R_ARM_JUMP24:
14351438
case R_ARM_CALL:
14361439
case R_ARM_THM_CALL:
14371440
if (ctx.arg.picThunk)
1438-
return make<ARMV4PILongBXThunk>(ctx, s, a);
1439-
return make<ARMV5LongLdrPcThunk>(ctx, s, a);
1441+
return std::make_unique<ARMV4PILongBXThunk>(ctx, s, a);
1442+
return std::make_unique<ARMV5LongLdrPcThunk>(ctx, s, a);
14401443
}
14411444
Fatal(ctx) << "relocation " << reloc << " to " << &s
14421445
<< " not supported for Armv5 or Armv6 targets";
@@ -1448,16 +1451,16 @@ static Thunk *addThunkArmv5v6(Ctx &ctx, RelType reloc, Symbol &s, int64_t a) {
14481451
// - MOVT and MOVW instructions cannot be used.
14491452
// - Only a limited number of instructions can access registers r8 and above
14501453
// - No interworking support is needed (all Thumb).
1451-
static Thunk *addThunkV6M(Ctx &ctx, const InputSection &isec, RelType reloc,
1452-
Symbol &s, int64_t a) {
1454+
static std::unique_ptr<Thunk> addThunkV6M(Ctx &ctx, const InputSection &isec,
1455+
RelType reloc, Symbol &s, int64_t a) {
14531456
const bool isPureCode = isec.getParent()->flags & SHF_ARM_PURECODE;
14541457
switch (reloc) {
14551458
case R_ARM_THM_JUMP19:
14561459
case R_ARM_THM_JUMP24:
14571460
case R_ARM_THM_CALL:
14581461
if (ctx.arg.isPic) {
14591462
if (!isPureCode)
1460-
return make<ThumbV6MPILongThunk>(ctx, s, a);
1463+
return std::make_unique<ThumbV6MPILongThunk>(ctx, s, a);
14611464

14621465
Fatal(ctx)
14631466
<< "relocation " << reloc << " to " << &s
@@ -1466,17 +1469,17 @@ static Thunk *addThunkV6M(Ctx &ctx, const InputSection &isec, RelType reloc,
14661469
llvm_unreachable("");
14671470
}
14681471
if (isPureCode)
1469-
return make<ThumbV6MABSXOLongThunk>(ctx, s, a);
1470-
return make<ThumbV6MABSLongThunk>(ctx, s, a);
1472+
return std::make_unique<ThumbV6MABSXOLongThunk>(ctx, s, a);
1473+
return std::make_unique<ThumbV6MABSLongThunk>(ctx, s, a);
14711474
}
14721475
Fatal(ctx) << "relocation " << reloc << " to " << &s
14731476
<< " not supported for Armv6-M targets";
14741477
llvm_unreachable("");
14751478
}
14761479

14771480
// Creates a thunk for Thumb-ARM interworking or branch range extension.
1478-
static Thunk *addThunkArm(Ctx &ctx, const InputSection &isec, RelType reloc,
1479-
Symbol &s, int64_t a) {
1481+
static std::unique_ptr<Thunk> addThunkArm(Ctx &ctx, const InputSection &isec,
1482+
RelType reloc, Symbol &s, int64_t a) {
14801483
// Decide which Thunk is needed based on:
14811484
// Available instruction set
14821485
// - An Arm Thunk can only be used if Arm state is available.
@@ -1508,47 +1511,49 @@ static Thunk *addThunkArm(Ctx &ctx, const InputSection &isec, RelType reloc,
15081511
case R_ARM_JUMP24:
15091512
case R_ARM_CALL:
15101513
if (ctx.arg.picThunk)
1511-
return make<ARMV7PILongThunk>(ctx, s, a);
1512-
return make<ARMV7ABSLongThunk>(ctx, s, a);
1514+
return std::make_unique<ARMV7PILongThunk>(ctx, s, a);
1515+
return std::make_unique<ARMV7ABSLongThunk>(ctx, s, a);
15131516
case R_ARM_THM_JUMP19:
15141517
case R_ARM_THM_JUMP24:
15151518
case R_ARM_THM_CALL:
15161519
if (ctx.arg.picThunk)
1517-
return make<ThumbV7PILongThunk>(ctx, s, a);
1518-
return make<ThumbV7ABSLongThunk>(ctx, s, a);
1520+
return std::make_unique<ThumbV7PILongThunk>(ctx, s, a);
1521+
return std::make_unique<ThumbV7ABSLongThunk>(ctx, s, a);
15191522
}
15201523
llvm_unreachable("");
15211524
}
15221525

1523-
static Thunk *addThunkAVR(Ctx &ctx, RelType type, Symbol &s, int64_t a) {
1526+
static std::unique_ptr<Thunk> addThunkAVR(Ctx &ctx, RelType type, Symbol &s,
1527+
int64_t a) {
15241528
switch (type) {
15251529
case R_AVR_LO8_LDI_GS:
15261530
case R_AVR_HI8_LDI_GS:
1527-
return make<AVRThunk>(ctx, s, a);
1531+
return std::make_unique<AVRThunk>(ctx, s, a);
15281532
default:
15291533
llvm_unreachable("");
15301534
}
15311535
}
15321536

1533-
static Thunk *addThunkMips(Ctx &ctx, RelType type, Symbol &s) {
1537+
static std::unique_ptr<Thunk> addThunkMips(Ctx &ctx, RelType type, Symbol &s) {
15341538
if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6(ctx))
1535-
return make<MicroMipsR6Thunk>(ctx, s);
1539+
return std::make_unique<MicroMipsR6Thunk>(ctx, s);
15361540
if (s.stOther & STO_MIPS_MICROMIPS)
1537-
return make<MicroMipsThunk>(ctx, s);
1538-
return make<MipsThunk>(ctx, s);
1541+
return std::make_unique<MicroMipsThunk>(ctx, s);
1542+
return std::make_unique<MipsThunk>(ctx, s);
15391543
}
15401544

1541-
static Thunk *addThunkPPC32(Ctx &ctx, const InputSection &isec,
1542-
const Relocation &rel, Symbol &s) {
1545+
static std::unique_ptr<Thunk> addThunkPPC32(Ctx &ctx, const InputSection &isec,
1546+
const Relocation &rel, Symbol &s) {
15431547
assert((rel.type == R_PPC_LOCAL24PC || rel.type == R_PPC_REL24 ||
15441548
rel.type == R_PPC_PLTREL24) &&
15451549
"unexpected relocation type for thunk");
15461550
if (s.isInPlt(ctx))
1547-
return make<PPC32PltCallStub>(ctx, isec, rel, s);
1548-
return make<PPC32LongThunk>(ctx, s, rel.addend);
1551+
return std::make_unique<PPC32PltCallStub>(ctx, isec, rel, s);
1552+
return std::make_unique<PPC32LongThunk>(ctx, s, rel.addend);
15491553
}
15501554

1551-
static Thunk *addThunkPPC64(Ctx &ctx, RelType type, Symbol &s, int64_t a) {
1555+
static std::unique_ptr<Thunk> addThunkPPC64(Ctx &ctx, RelType type, Symbol &s,
1556+
int64_t a) {
15521557
assert((type == R_PPC64_REL14 || type == R_PPC64_REL24 ||
15531558
type == R_PPC64_REL24_NOTOC) &&
15541559
"unexpected relocation type for thunk");
@@ -1558,27 +1563,30 @@ static Thunk *addThunkPPC64(Ctx &ctx, RelType type, Symbol &s, int64_t a) {
15581563
if (type == R_PPC64_REL24_NOTOC)
15591564
ctx.target->ppc64DynamicSectionOpt = 0x2;
15601565

1561-
if (s.isInPlt(ctx))
1562-
return type == R_PPC64_REL24_NOTOC
1563-
? (Thunk *)make<PPC64R12SetupStub>(ctx, s, /*gotPlt=*/true)
1564-
: (Thunk *)make<PPC64PltCallStub>(ctx, s);
1566+
if (s.isInPlt(ctx)) {
1567+
if (type == R_PPC64_REL24_NOTOC)
1568+
return std::make_unique<PPC64R12SetupStub>(ctx, s,
1569+
/*gotPlt=*/true);
1570+
return std::make_unique<PPC64PltCallStub>(ctx, s);
1571+
}
15651572

15661573
// This check looks at the st_other bits of the callee. If the value is 1
15671574
// then the callee clobbers the TOC and we need an R2 save stub when RelType
15681575
// is R_PPC64_REL14 or R_PPC64_REL24.
15691576
if ((type == R_PPC64_REL14 || type == R_PPC64_REL24) && (s.stOther >> 5) == 1)
1570-
return make<PPC64R2SaveStub>(ctx, s, a);
1577+
return std::make_unique<PPC64R2SaveStub>(ctx, s, a);
15711578

15721579
if (type == R_PPC64_REL24_NOTOC)
1573-
return make<PPC64R12SetupStub>(ctx, s, /*gotPlt=*/false);
1580+
return std::make_unique<PPC64R12SetupStub>(ctx, s, /*gotPlt=*/false);
15741581

15751582
if (ctx.arg.picThunk)
1576-
return make<PPC64PILongBranchThunk>(ctx, s, a);
1583+
return std::make_unique<PPC64PILongBranchThunk>(ctx, s, a);
15771584

1578-
return make<PPC64PDLongBranchThunk>(ctx, s, a);
1585+
return std::make_unique<PPC64PDLongBranchThunk>(ctx, s, a);
15791586
}
15801587

1581-
Thunk *elf::addThunk(Ctx &ctx, const InputSection &isec, Relocation &rel) {
1588+
std::unique_ptr<Thunk> elf::addThunk(Ctx &ctx, const InputSection &isec,
1589+
Relocation &rel) {
15821590
Symbol &s = *rel.sym;
15831591
int64_t a = rel.addend;
15841592

@@ -1600,10 +1608,10 @@ Thunk *elf::addThunk(Ctx &ctx, const InputSection &isec, Relocation &rel) {
16001608
}
16011609
}
16021610

1603-
Thunk *elf::addLandingPadThunk(Ctx &ctx, Symbol &s, int64_t a) {
1611+
std::unique_ptr<Thunk> elf::addLandingPadThunk(Ctx &ctx, Symbol &s, int64_t a) {
16041612
switch (ctx.arg.emachine) {
16051613
case EM_AARCH64:
1606-
return make<AArch64BTILandingPadThunk>(ctx, s, a);
1614+
return std::make_unique<AArch64BTILandingPadThunk>(ctx, s, a);
16071615
default:
16081616
llvm_unreachable("add landing pad only supported for AArch64");
16091617
}

lld/ELF/Thunks.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,12 @@ class Thunk {
7676

7777
// For a Relocation to symbol S create a Thunk to be added to a synthetic
7878
// ThunkSection.
79-
Thunk *addThunk(Ctx &, const InputSection &isec, Relocation &rel);
79+
std::unique_ptr<Thunk> addThunk(Ctx &, const InputSection &isec,
80+
Relocation &rel);
8081

8182
// Create a landing pad Thunk for use when indirect branches from Thunks
8283
// are restricted.
83-
Thunk *addLandingPadThunk(Ctx &, Symbol &s, int64_t a);
84+
std::unique_ptr<Thunk> addLandingPadThunk(Ctx &, Symbol &s, int64_t a);
8485

8586
void writePPC32PltCallStub(Ctx &, uint8_t *buf, uint64_t gotPltVA,
8687
const InputFile *file, int64_t addend);

lld/ELF/Writer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ template <class ELFT> class Writer {
4949
public:
5050
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
5151

52-
Writer(Ctx &ctx) : ctx(ctx), buffer(ctx.e.outputBuffer) {}
52+
Writer(Ctx &ctx) : ctx(ctx), buffer(ctx.e.outputBuffer), tc(ctx) {}
5353

5454
void run();
5555

@@ -82,6 +82,8 @@ template <class ELFT> class Writer {
8282

8383
Ctx &ctx;
8484
std::unique_ptr<FileOutputBuffer> &buffer;
85+
// ThunkCreator holds Thunks that are used at writeTo time.
86+
ThunkCreator tc;
8587

8688
void addRelIpltSymbols();
8789
void addStartEndSymbols();
@@ -1448,7 +1450,6 @@ static void finalizeSynthetic(Ctx &ctx, SyntheticSection *sec) {
14481450
// in Writer<ELFT>::finalizeSections().
14491451
template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
14501452
llvm::TimeTraceScope timeScope("Finalize address dependent content");
1451-
ThunkCreator tc(ctx);
14521453
AArch64Err843419Patcher a64p(ctx);
14531454
ARMErr657417Patcher a32p(ctx);
14541455
ctx.script->assignAddresses();

0 commit comments

Comments
 (0)