Skip to content

Commit 8777abe

Browse files
committed
[LLD][MachO] Refactor LOH code
1 parent a2ce564 commit 8777abe

File tree

1 file changed

+28
-45
lines changed

1 file changed

+28
-45
lines changed

lld/MachO/Arch/ARM64.cpp

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include "lld/Common/ErrorHandler.h"
1616
#include "mach-o/compact_unwind_encoding.h"
1717
#include "llvm/ADT/SmallVector.h"
18-
#include "llvm/ADT/StringRef.h"
1918
#include "llvm/BinaryFormat/MachO.h"
2019
#include "llvm/Support/Endian.h"
2120
#include "llvm/Support/LEB128.h"
@@ -393,25 +392,26 @@ static void writeImmediateLdr(void *loc, const Ldr &ldr) {
393392
// ->
394393
// adr xM, _foo
395394
// nop
396-
static void applyAdrpAdd(uint8_t *buf, const ConcatInputSection *isec,
395+
static bool applyAdrpAdd(uint8_t *buf, const ConcatInputSection *isec,
397396
uint64_t offset1, uint64_t offset2) {
398397
uint32_t ins1 = read32le(buf + offset1);
399398
uint32_t ins2 = read32le(buf + offset2);
400399
Adrp adrp;
401400
Add add;
402401
if (!parseAdrp(ins1, adrp) || !parseAdd(ins2, add))
403-
return;
402+
return false;
404403
if (adrp.destRegister != add.srcRegister)
405-
return;
404+
return false;
406405

407406
uint64_t addr1 = isec->getVA() + offset1;
408407
uint64_t referent = pageBits(addr1) + adrp.addend + add.addend;
409408
int64_t delta = referent - addr1;
410409
if (!isValidAdrOffset(delta))
411-
return;
410+
return false;
412411

413412
writeAdr(buf + offset1, add.destRegister, delta);
414413
writeNop(buf + offset2);
414+
return true;
415415
}
416416

417417
// Transforms two adrp instructions into a single adrp if their referent
@@ -496,16 +496,12 @@ static void applyAdrpAddLdr(uint8_t *buf, const ConcatInputSection *isec,
496496
uint64_t offset1, uint64_t offset2,
497497
uint64_t offset3) {
498498
uint32_t ins1 = read32le(buf + offset1);
499-
Adrp adrp;
500-
if (!parseAdrp(ins1, adrp))
501-
return;
502499
uint32_t ins2 = read32le(buf + offset2);
503-
Add add;
504-
if (!parseAdd(ins2, add))
505-
return;
506500
uint32_t ins3 = read32le(buf + offset3);
501+
Adrp adrp;
502+
Add add;
507503
Ldr ldr;
508-
if (!parseLdr(ins3, ldr))
504+
if (!parseAdrp(ins1, adrp) || !parseAdd(ins2, add) || !parseLdr(ins3, ldr))
509505
return;
510506
if (adrp.destRegister != add.srcRegister)
511507
return;
@@ -528,18 +524,8 @@ static void applyAdrpAddLdr(uint8_t *buf, const ConcatInputSection *isec,
528524
return;
529525
}
530526

531-
// Load the target address into a register and load from there indirectly.
532-
// adr x1, _foo
533-
// nop
534-
// ldr x2, [x1, #off]
535-
int64_t adrOffset = referent - addr1;
536-
if (isValidAdrOffset(adrOffset)) {
537-
writeAdr(buf + offset1, ldr.baseRegister, adrOffset);
538-
// Note: ld64 moves the offset into the adr instruction for AdrpAddLdr, but
539-
// not for AdrpLdrGotLdr. Its effect is the same either way.
540-
writeNop(buf + offset2);
527+
if (applyAdrpAdd(buf, isec, offset1, offset2))
541528
return;
542-
}
543529

544530
// Move the target's page offset into the ldr's immediate offset.
545531
// adrp x0, _foo@PAGE
@@ -575,12 +561,10 @@ static void applyAdrpLdrGotLdr(uint8_t *buf, const ConcatInputSection *isec,
575561
// ldr x3, [x2, #off]
576562

577563
uint32_t ins1 = read32le(buf + offset1);
578-
Adrp adrp;
579-
if (!parseAdrp(ins1, adrp))
580-
return;
581564
uint32_t ins3 = read32le(buf + offset3);
565+
Adrp adrp;
582566
Ldr ldr3;
583-
if (!parseLdr(ins3, ldr3))
567+
if (!parseAdrp(ins1, adrp) || !parseLdr(ins3, ldr3))
584568
return;
585569

586570
if (ldr2.baseRegister != adrp.destRegister)
@@ -607,33 +591,32 @@ static void applyAdrpLdrGotLdr(uint8_t *buf, const ConcatInputSection *isec,
607591
}
608592
}
609593

610-
static uint64_t readValue(const uint8_t *&ptr, const uint8_t *end) {
611-
unsigned int n = 0;
612-
uint64_t value = decodeULEB128(ptr, &n, end);
613-
ptr += n;
614-
return value;
615-
}
616-
617594
template <typename Callback>
618595
static void forEachHint(ArrayRef<uint8_t> data, Callback callback) {
619596
std::array<uint64_t, 3> args;
620597

621-
for (const uint8_t *p = data.begin(), *end = data.end(); p < end;) {
622-
uint64_t type = readValue(p, end);
598+
auto readNext = [&]() -> uint64_t {
599+
unsigned int n = 0;
600+
uint64_t value = decodeULEB128(data.data(), &n, data.end());
601+
data = data.drop_front(n);
602+
return value;
603+
};
604+
605+
while (!data.empty()) {
606+
uint64_t type = readNext();
623607
if (type == 0)
624608
break;
625609

626-
uint64_t argCount = readValue(p, end);
610+
uint64_t argCount = readNext();
611+
for (unsigned i = 0; i < argCount; ++i) {
612+
uint64_t arg = readNext();
613+
if (i < 3)
614+
args[i] = arg;
615+
}
627616
// All known LOH types as of 2022-09 have 3 or fewer arguments; skip others.
628-
if (argCount > 3) {
629-
for (unsigned i = 0; i < argCount; ++i)
630-
readValue(p, end);
617+
if (argCount > 3)
631618
continue;
632-
}
633-
634-
for (unsigned i = 0; i < argCount; ++i)
635-
args[i] = readValue(p, end);
636-
callback(type, ArrayRef<uint64_t>(args.data(), argCount));
619+
callback(type, ArrayRef(args.data(), argCount));
637620
}
638621
}
639622

0 commit comments

Comments
 (0)