Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -802,6 +802,8 @@ case Triple::arm: case Triple::thumb: return EM_ARM; + case Triple::avr: + return EM_AVR; case Triple::mips: case Triple::mipsel: case Triple::mips64: Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -230,6 +230,14 @@ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; }; +class AVRTargetInfo final : public TargetInfo { +public: + RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const override; + int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; + void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; +}; + template class MipsTargetInfo final : public TargetInfo { public: MipsTargetInfo(); @@ -260,6 +268,8 @@ return make(); case EM_ARM: return make(); + case EM_AVR: + return make(); case EM_MIPS: switch (Config->EKind) { case ELF32LEKind: @@ -2036,6 +2046,54 @@ } } +template +static void applyAVRReloc(uint8_t *Loc, uint32_t Type, uint64_t V) { + uint32_t Mask = 0xffffffff >> (32 - BSIZE); + uint32_t Instr = read32le(Loc); + if (SHIFT > 0) + checkAlignment<(1 << SHIFT)>(Loc, V, Type); + checkInt(Loc, V, Type); + write32le(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); +} + +RelExpr AVRTargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S, + const uint8_t *Loc) const { + switch (Type) { + case R_AVR_32: + case R_AVR_CALL: + return R_ABS; + default: + error(toString(S.File) + ": unknown relocation type: " + toString(Type)); + return R_HINT; + } +} + +int64_t AVRTargetInfo::getImplicitAddend(const uint8_t *Buf, + uint32_t Type) const { + switch (Type) { + default: + return 0; + case R_AVR_32: + return SignExtend64<32>(read32le(Buf)); + case R_AVR_CALL: + return SignExtend64<25>(read32le(Buf) << 1); + } +} + +void AVRTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type, + uint64_t Val) const { + switch (Type) { + case R_AVR_32: + write32le(Loc, Val); + break; + case R_AVR_CALL: + applyAVRReloc<23, 1>(Loc, Type, Val); + break; + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); + } +} + template MipsTargetInfo::MipsTargetInfo() { GotPltHeaderEntriesNum = 2; DefaultMaxPageSize = 65536; Index: test/ELF/basic-avr.s =================================================================== --- test/ELF/basic-avr.s +++ test/ELF/basic-avr.s @@ -0,0 +1,17 @@ +# REQUIRES: avr +# RUN: llvm-mc -filetype=obj -triple=avr-unknown-linux -mcpu=atmega328p %s -o %t1.o +# RUN: ld.lld %t1.o -o %t.exe +# RUN: llvm-objdump -d %t.exe | FileCheck %s + +main: + call foo + +foo: + jmp foo + +# CHECK: Disassembly of section .text: +# CHECK-NEXT: main: +# CHECK-NEXT: 11000: 02 88 00 00 +# +# CHECK: foo: +# CHECK-NEXT: 11004: 02 88 00 00 Index: test/lit.cfg =================================================================== --- test/lit.cfg +++ test/lit.cfg @@ -246,6 +246,8 @@ config.available_features.add('aarch64') if re.search(r'ARM', archs): config.available_features.add('arm') +if re.search(r'AVR', archs): + config.available_features.add('avr') if re.search(r'Mips', archs): config.available_features.add('mips') if re.search(r'X86', archs):