1 | //===-- AVRTargetObjectFile.cpp - AVR Object Files ------------------------===// |
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 "AVRTargetObjectFile.h" |
10 | #include "AVRTargetMachine.h" |
11 | |
12 | #include "llvm/BinaryFormat/ELF.h" |
13 | #include "llvm/IR/GlobalValue.h" |
14 | #include "llvm/IR/Mangler.h" |
15 | #include "llvm/MC/MCContext.h" |
16 | #include "llvm/MC/MCSectionELF.h" |
17 | |
18 | #include "AVR.h" |
19 | |
20 | namespace llvm { |
21 | void AVRTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) { |
22 | Base::Initialize(Ctx, TM); |
23 | ProgmemDataSection = |
24 | Ctx.getELFSection(Section: ".progmem.data" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC); |
25 | Progmem1DataSection = |
26 | Ctx.getELFSection(Section: ".progmem1.data" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC); |
27 | Progmem2DataSection = |
28 | Ctx.getELFSection(Section: ".progmem2.data" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC); |
29 | Progmem3DataSection = |
30 | Ctx.getELFSection(Section: ".progmem3.data" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC); |
31 | Progmem4DataSection = |
32 | Ctx.getELFSection(Section: ".progmem4.data" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC); |
33 | Progmem5DataSection = |
34 | Ctx.getELFSection(Section: ".progmem5.data" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC); |
35 | } |
36 | |
37 | MCSection *AVRTargetObjectFile::SelectSectionForGlobal( |
38 | const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { |
39 | // Global values in flash memory are placed in the progmem*.data section |
40 | // unless they already have a user assigned section. |
41 | const auto &AVRTM = static_cast<const AVRTargetMachine &>(TM); |
42 | if (AVR::isProgramMemoryAddress(V: GO) && !GO->hasSection() && |
43 | Kind.isReadOnly()) { |
44 | // The AVR subtarget should support LPM to access section '.progmem*.data'. |
45 | if (!AVRTM.getSubtargetImpl()->hasLPM()) { |
46 | // TODO: Get the global object's location in source file. |
47 | getContext().reportError( |
48 | L: SMLoc(), |
49 | Msg: "Current AVR subtarget does not support accessing program memory" ); |
50 | return Base::SelectSectionForGlobal(GO, Kind, TM); |
51 | } |
52 | // The AVR subtarget should support ELPM to access section |
53 | // '.progmem[1|2|3|4|5].data'. |
54 | if (!AVRTM.getSubtargetImpl()->hasELPM() && |
55 | AVR::getAddressSpace(V: GO) != AVR::ProgramMemory) { |
56 | // TODO: Get the global object's location in source file. |
57 | getContext().reportError(L: SMLoc(), |
58 | Msg: "Current AVR subtarget does not support " |
59 | "accessing extended program memory" ); |
60 | return ProgmemDataSection; |
61 | } |
62 | switch (AVR::getAddressSpace(V: GO)) { |
63 | case AVR::ProgramMemory: // address space 1 |
64 | return ProgmemDataSection; |
65 | case AVR::ProgramMemory1: // address space 2 |
66 | return Progmem1DataSection; |
67 | case AVR::ProgramMemory2: // address space 3 |
68 | return Progmem2DataSection; |
69 | case AVR::ProgramMemory3: // address space 4 |
70 | return Progmem3DataSection; |
71 | case AVR::ProgramMemory4: // address space 5 |
72 | return Progmem4DataSection; |
73 | case AVR::ProgramMemory5: // address space 6 |
74 | return Progmem5DataSection; |
75 | default: |
76 | llvm_unreachable("unexpected program memory index" ); |
77 | } |
78 | } |
79 | |
80 | // Otherwise, we work the same way as ELF. |
81 | return Base::SelectSectionForGlobal(GO, Kind, TM); |
82 | } |
83 | } // end of namespace llvm |
84 | |