diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp --- a/lld/ELF/Arch/AVR.cpp +++ b/lld/ELF/Arch/AVR.cpp @@ -43,6 +43,7 @@ class AVR final : public TargetInfo { public: AVR(); + uint32_t calcEFlags() const override; RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; void relocate(uint8_t *loc, const Relocation &rel, @@ -196,3 +197,28 @@ static AVR target; return ⌖ } + +static uint32_t getEFlags(InputFile *file) { + return cast>(file)->getObj().getHeader().e_flags; +} + +uint32_t AVR::calcEFlags() const { + assert(!objectFiles.empty()); + + uint32_t flags = getEFlags(objectFiles[0]); + bool hasLinkRelaxFlag = flags & EF_AVR_LINKRELAX_PREPARED; + + for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { + uint32_t objFlags = getEFlags(f); + if ((objFlags & EF_AVR_ARCH_MASK) != (flags & EF_AVR_ARCH_MASK)) + error(toString(f) + + ": cannot link object files with incompatible target ISA"); + if (!(objFlags & EF_AVR_LINKRELAX_PREPARED)) + hasLinkRelaxFlag = false; + } + + if (!hasLinkRelaxFlag) + flags &= ~EF_AVR_LINKRELAX_PREPARED; + + return flags; +} diff --git a/lld/test/ELF/avr-flags.s b/lld/test/ELF/avr-flags.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/avr-flags.s @@ -0,0 +1,15 @@ +; RUN: llvm-mc -filetype=obj -triple=avr -mcpu=avr5 %s -o %t-v5 +; RUN: llvm-mc -filetype=obj -triple=avr -mcpu=avrxmega3 %s -o %t-xmega3 +; RUN: ld.lld %t-v5 -o %t-v5.out +; RUN: ld.lld %t-xmega3 -o %t-xmega3.out +; RUN: llvm-readobj -h %t-v5.out | FileCheck --check-prefix V5 %s +; RUN: llvm-readobj -h %t-xmega3.out | FileCheck --check-prefix XMEGA3 %s + +;; Ensure LLD won't silently mix object files targeting different ISAs. +; RUN: not ld.lld %t-v5 %t-xmega3 -o /dev/null 2>&1 | FileCheck --check-prefix ERR %s +; ERR: error: {{.*}}: cannot link object files with incompatible target ISA + +; V5: Flags [ (0x5) +; V5: EF_AVR_ARCH_AVR5 (0x5) +; XMEGA3: Flags [ (0x67) +; XMEGA3: EF_AVR_ARCH_XMEGA3 (0x67)