| 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 | |