1//===-- AVRELFObjectWriter.cpp - AVR ELF Writer ---------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "MCTargetDesc/AVRFixupKinds.h"
10#include "MCTargetDesc/AVRMCTargetDesc.h"
11
12#include "llvm/MC/MCAssembler.h"
13#include "llvm/MC/MCELFObjectWriter.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCObjectWriter.h"
16#include "llvm/MC/MCSection.h"
17#include "llvm/MC/MCValue.h"
18#include "llvm/Support/ErrorHandling.h"
19
20namespace llvm {
21
22/// Writes AVR machine code into an ELF32 object file.
23class AVRELFObjectWriter : public MCELFObjectTargetWriter {
24public:
25  AVRELFObjectWriter(uint8_t OSABI);
26
27  virtual ~AVRELFObjectWriter() {}
28
29  unsigned getRelocType(MCContext &Ctx,
30                        const MCValue &Target,
31                        const MCFixup &Fixup,
32                        bool IsPCRel) const override;
33};
34
35AVRELFObjectWriter::AVRELFObjectWriter(uint8_t OSABI)
36    : MCELFObjectTargetWriter(false, OSABI, ELF::EM_AVR, true) {}
37
38unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx,
39                                          const MCValue &Target,
40                                          const MCFixup &Fixup,
41                                          bool IsPCRel) const {
42  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
43  switch ((unsigned) Fixup.getKind()) {
44  case FK_Data_1:
45    switch (Modifier) {
46    default:
47      llvm_unreachable("Unsupported Modifier");
48    case MCSymbolRefExpr::VK_None:
49      return ELF::R_AVR_8;
50    case MCSymbolRefExpr::VK_AVR_DIFF8:
51      return ELF::R_AVR_DIFF8;
52    case MCSymbolRefExpr::VK_AVR_LO8:
53      return ELF::R_AVR_8_LO8;
54    case MCSymbolRefExpr::VK_AVR_HI8:
55      return ELF::R_AVR_8_HI8;
56    case MCSymbolRefExpr::VK_AVR_HLO8:
57      return ELF::R_AVR_8_HLO8;
58    }
59  case FK_Data_4:
60    switch (Modifier) {
61    default:
62      llvm_unreachable("Unsupported Modifier");
63    case MCSymbolRefExpr::VK_None:
64      return ELF::R_AVR_32;
65    case MCSymbolRefExpr::VK_AVR_DIFF32:
66      return ELF::R_AVR_DIFF32;
67    }
68  case FK_Data_2:
69    switch (Modifier) {
70    default:
71      llvm_unreachable("Unsupported Modifier");
72    case MCSymbolRefExpr::VK_None:
73      return ELF::R_AVR_16;
74    case MCSymbolRefExpr::VK_AVR_NONE:
75      return ELF::R_AVR_16_PM;
76    case MCSymbolRefExpr::VK_AVR_DIFF16:
77      return ELF::R_AVR_DIFF16;
78    }
79  case AVR::fixup_32:
80    return ELF::R_AVR_32;
81  case AVR::fixup_7_pcrel:
82    return ELF::R_AVR_7_PCREL;
83  case AVR::fixup_13_pcrel:
84    return ELF::R_AVR_13_PCREL;
85  case AVR::fixup_16:
86    return ELF::R_AVR_16;
87  case AVR::fixup_16_pm:
88    return ELF::R_AVR_16_PM;
89  case AVR::fixup_lo8_ldi:
90    return ELF::R_AVR_LO8_LDI;
91  case AVR::fixup_hi8_ldi:
92    return ELF::R_AVR_HI8_LDI;
93  case AVR::fixup_hh8_ldi:
94    return ELF::R_AVR_HH8_LDI;
95  case AVR::fixup_lo8_ldi_neg:
96    return ELF::R_AVR_LO8_LDI_NEG;
97  case AVR::fixup_hi8_ldi_neg:
98    return ELF::R_AVR_HI8_LDI_NEG;
99  case AVR::fixup_hh8_ldi_neg:
100    return ELF::R_AVR_HH8_LDI_NEG;
101  case AVR::fixup_lo8_ldi_pm:
102    return ELF::R_AVR_LO8_LDI_PM;
103  case AVR::fixup_hi8_ldi_pm:
104    return ELF::R_AVR_HI8_LDI_PM;
105  case AVR::fixup_hh8_ldi_pm:
106    return ELF::R_AVR_HH8_LDI_PM;
107  case AVR::fixup_lo8_ldi_pm_neg:
108    return ELF::R_AVR_LO8_LDI_PM_NEG;
109  case AVR::fixup_hi8_ldi_pm_neg:
110    return ELF::R_AVR_HI8_LDI_PM_NEG;
111  case AVR::fixup_hh8_ldi_pm_neg:
112    return ELF::R_AVR_HH8_LDI_PM_NEG;
113  case AVR::fixup_call:
114    return ELF::R_AVR_CALL;
115  case AVR::fixup_ldi:
116    return ELF::R_AVR_LDI;
117  case AVR::fixup_6:
118    return ELF::R_AVR_6;
119  case AVR::fixup_6_adiw:
120    return ELF::R_AVR_6_ADIW;
121  case AVR::fixup_ms8_ldi:
122    return ELF::R_AVR_MS8_LDI;
123  case AVR::fixup_ms8_ldi_neg:
124    return ELF::R_AVR_MS8_LDI_NEG;
125  case AVR::fixup_lo8_ldi_gs:
126    return ELF::R_AVR_LO8_LDI_GS;
127  case AVR::fixup_hi8_ldi_gs:
128    return ELF::R_AVR_HI8_LDI_GS;
129  case AVR::fixup_8:
130    return ELF::R_AVR_8;
131  case AVR::fixup_8_lo8:
132    return ELF::R_AVR_8_LO8;
133  case AVR::fixup_8_hi8:
134    return ELF::R_AVR_8_HI8;
135  case AVR::fixup_8_hlo8:
136    return ELF::R_AVR_8_HLO8;
137  case AVR::fixup_diff8:
138    return ELF::R_AVR_DIFF8;
139  case AVR::fixup_diff16:
140    return ELF::R_AVR_DIFF16;
141  case AVR::fixup_diff32:
142    return ELF::R_AVR_DIFF32;
143  case AVR::fixup_lds_sts_16:
144    return ELF::R_AVR_LDS_STS_16;
145  case AVR::fixup_port6:
146    return ELF::R_AVR_PORT6;
147  case AVR::fixup_port5:
148    return ELF::R_AVR_PORT5;
149  default:
150    llvm_unreachable("invalid fixup kind!");
151  }
152}
153
154std::unique_ptr<MCObjectTargetWriter> createAVRELFObjectWriter(uint8_t OSABI) {
155  return std::make_unique<AVRELFObjectWriter>(OSABI);
156}
157
158} // end of namespace llvm
159
160