diff options
Diffstat (limited to 'contrib/llvm/tools/lld/COFF/Writer.cpp')
| -rw-r--r-- | contrib/llvm/tools/lld/COFF/Writer.cpp | 60 | 
1 files changed, 43 insertions, 17 deletions
| diff --git a/contrib/llvm/tools/lld/COFF/Writer.cpp b/contrib/llvm/tools/lld/COFF/Writer.cpp index 258796ea6057..6acfaf9a4454 100644 --- a/contrib/llvm/tools/lld/COFF/Writer.cpp +++ b/contrib/llvm/tools/lld/COFF/Writer.cpp @@ -306,16 +306,31 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {  // Check whether the target address S is in range from a relocation  // of type RelType at address P.  static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) { -  assert(Config->Machine == ARMNT); -  int64_t Diff = AbsoluteDifference(S, P + 4) + Margin; -  switch (RelType) { -  case IMAGE_REL_ARM_BRANCH20T: -    return isInt<21>(Diff); -  case IMAGE_REL_ARM_BRANCH24T: -  case IMAGE_REL_ARM_BLX23T: -    return isInt<25>(Diff); -  default: -    return true; +  if (Config->Machine == ARMNT) { +    int64_t Diff = AbsoluteDifference(S, P + 4) + Margin; +    switch (RelType) { +    case IMAGE_REL_ARM_BRANCH20T: +      return isInt<21>(Diff); +    case IMAGE_REL_ARM_BRANCH24T: +    case IMAGE_REL_ARM_BLX23T: +      return isInt<25>(Diff); +    default: +      return true; +    } +  } else if (Config->Machine == ARM64) { +    int64_t Diff = AbsoluteDifference(S, P) + Margin; +    switch (RelType) { +    case IMAGE_REL_ARM64_BRANCH26: +      return isInt<28>(Diff); +    case IMAGE_REL_ARM64_BRANCH19: +      return isInt<21>(Diff); +    case IMAGE_REL_ARM64_BRANCH14: +      return isInt<16>(Diff); +    default: +      return true; +    } +  } else { +    llvm_unreachable("Unexpected architecture");    }  } @@ -327,7 +342,17 @@ getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,    Defined *&LastThunk = LastThunks[Target->getRVA()];    if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin))      return {LastThunk, false}; -  RangeExtensionThunk *C = make<RangeExtensionThunk>(Target); +  Chunk *C; +  switch (Config->Machine) { +  case ARMNT: +    C = make<RangeExtensionThunkARM>(Target); +    break; +  case ARM64: +    C = make<RangeExtensionThunkARM64>(Target); +    break; +  default: +    llvm_unreachable("Unexpected architecture"); +  }    Defined *D = make<DefinedSynthetic>("", C);    LastThunk = D;    return {D, true}; @@ -344,14 +369,14 @@ getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,  // After adding thunks, we verify that all relocations are in range (with  // no extra margin requirements). If this failed, we restart (throwing away  // the previously created thunks) and retry with a wider margin. -static bool createThunks(std::vector<Chunk *> &Chunks, int Margin) { +static bool createThunks(OutputSection *OS, int Margin) {    bool AddressesChanged = false;    DenseMap<uint64_t, Defined *> LastThunks;    size_t ThunksSize = 0;    // Recheck Chunks.size() each iteration, since we can insert more    // elements into it. -  for (size_t I = 0; I != Chunks.size(); ++I) { -    SectionChunk *SC = dyn_cast_or_null<SectionChunk>(Chunks[I]); +  for (size_t I = 0; I != OS->Chunks.size(); ++I) { +    SectionChunk *SC = dyn_cast_or_null<SectionChunk>(OS->Chunks[I]);      if (!SC)        continue;      size_t ThunkInsertionSpot = I + 1; @@ -388,7 +413,8 @@ static bool createThunks(std::vector<Chunk *> &Chunks, int Margin) {          Chunk *ThunkChunk = Thunk->getChunk();          ThunkChunk->setRVA(              ThunkInsertionRVA); // Estimate of where it will be located. -        Chunks.insert(Chunks.begin() + ThunkInsertionSpot, ThunkChunk); +        ThunkChunk->setOutputSection(OS); +        OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk);          ThunkInsertionSpot++;          ThunksSize += ThunkChunk->getSize();          ThunkInsertionRVA += ThunkChunk->getSize(); @@ -428,7 +454,7 @@ static bool verifyRanges(const std::vector<Chunk *> Chunks) {  // Assign addresses and add thunks if necessary.  void Writer::finalizeAddresses() {    assignAddresses(); -  if (Config->Machine != ARMNT) +  if (Config->Machine != ARMNT && Config->Machine != ARM64)      return;    size_t OrigNumChunks = 0; @@ -477,7 +503,7 @@ void Writer::finalizeAddresses() {      // to avoid things going out of range due to the added thunks.      bool AddressesChanged = false;      for (OutputSection *Sec : OutputSections) -      AddressesChanged |= createThunks(Sec->Chunks, Margin); +      AddressesChanged |= createThunks(Sec, Margin);      // If the verification above thought we needed thunks, we should have      // added some.      assert(AddressesChanged); | 
