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