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-
617594template <typename Callback>
618595static 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