Skip to content

Commit

Permalink
[AVR][MC] Generate section '.progmemX.data' for extended flash banks
Browse files Browse the repository at this point in the history
Reviewed By: aykevl

Differential Revision: https://reviews.llvm.org/D115987
  • Loading branch information
benshi001 committed Jan 20, 2022
1 parent 34570f4 commit c1dd607
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 10 deletions.
36 changes: 31 additions & 5 deletions llvm/lib/Target/AVR/AVR.h
Expand Up @@ -38,17 +38,43 @@ void initializeAVRRelaxMemPass(PassRegistry &);
namespace AVR {

/// An integer that identifies all of the supported AVR address spaces.
enum AddressSpace { DataMemory, ProgramMemory };
enum AddressSpace {
DataMemory,
ProgramMemory,
ProgramMemory1,
ProgramMemory2,
ProgramMemory3,
ProgramMemory4,
ProgramMemory5,
NumAddrSpaces,
};

/// Checks if a given type is a pointer to program memory.
template <typename T> bool isProgramMemoryAddress(T *V) {
return cast<PointerType>(V->getType())->getAddressSpace() == ProgramMemory;
auto *PT = cast<PointerType>(V->getType());
assert(PT != nullptr && "unexpected MemSDNode");
return PT->getAddressSpace() == ProgramMemory ||
PT->getAddressSpace() == ProgramMemory1 ||
PT->getAddressSpace() == ProgramMemory2 ||
PT->getAddressSpace() == ProgramMemory3 ||
PT->getAddressSpace() == ProgramMemory4 ||
PT->getAddressSpace() == ProgramMemory5;
}

inline bool isProgramMemoryAccess(MemSDNode const *N) {
auto V = N->getMemOperand()->getValue();
template <typename T> AddressSpace getAddressSpace(T *V) {
auto *PT = cast<PointerType>(V->getType());
assert(PT != nullptr && "unexpected MemSDNode");
unsigned AS = PT->getAddressSpace();
if (AS < NumAddrSpaces)
return static_cast<AddressSpace>(AS);
return NumAddrSpaces;
}

return (V != nullptr) ? isProgramMemoryAddress(V) : false;
inline bool isProgramMemoryAccess(MemSDNode const *N) {
auto *V = N->getMemOperand()->getValue();
if (V != nullptr && isProgramMemoryAddress(V))
return true;
return false;
}

} // end of namespace AVR
Expand Down
53 changes: 50 additions & 3 deletions llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "AVRTargetObjectFile.h"
#include "AVRTargetMachine.h"

#include "llvm/BinaryFormat/ELF.h"
#include "llvm/IR/DerivedTypes.h"
Expand All @@ -22,14 +23,60 @@ void AVRTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) {
Base::Initialize(Ctx, TM);
ProgmemDataSection =
Ctx.getELFSection(".progmem.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
Progmem1DataSection =
Ctx.getELFSection(".progmem1.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
Progmem2DataSection =
Ctx.getELFSection(".progmem2.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
Progmem3DataSection =
Ctx.getELFSection(".progmem3.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
Progmem4DataSection =
Ctx.getELFSection(".progmem4.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
Progmem5DataSection =
Ctx.getELFSection(".progmem5.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
}

MCSection *AVRTargetObjectFile::SelectSectionForGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
// Global values in flash memory are placed in the progmem.data section
// Global values in flash memory are placed in the progmem*.data section
// unless they already have a user assigned section.
if (AVR::isProgramMemoryAddress(GO) && !GO->hasSection() && Kind.isReadOnly())
return ProgmemDataSection;
const auto &AVRTM = static_cast<const AVRTargetMachine &>(TM);
if (AVR::isProgramMemoryAddress(GO) && !GO->hasSection() &&
Kind.isReadOnly()) {
// The AVR subtarget should support LPM to access section '.progmem*.data'.
if (!AVRTM.getSubtargetImpl()->hasLPM()) {
// TODO: Get the global object's location in source file.
getContext().reportError(
SMLoc(),
"Current AVR subtarget does not support accessing program memory");
return Base::SelectSectionForGlobal(GO, Kind, TM);
}
// The AVR subtarget should support ELPM to access section
// '.progmem[1|2|3|4|5].data'.
if (!AVRTM.getSubtargetImpl()->hasELPM() &&
AVR::getAddressSpace(GO) != AVR::ProgramMemory) {
// TODO: Get the global object's location in source file.
getContext().reportError(SMLoc(),
"Current AVR subtarget does not support "
"accessing extended program memory");
return ProgmemDataSection;
}
switch (AVR::getAddressSpace(GO)) {
case AVR::ProgramMemory: // address space 1
return ProgmemDataSection;
case AVR::ProgramMemory1: // address space 2
return Progmem1DataSection;
case AVR::ProgramMemory2: // address space 3
return Progmem2DataSection;
case AVR::ProgramMemory3: // address space 4
return Progmem3DataSection;
case AVR::ProgramMemory4: // address space 5
return Progmem4DataSection;
case AVR::ProgramMemory5: // address space 6
return Progmem5DataSection;
default:
llvm_unreachable("unexpected program memory index");
}
}

// Otherwise, we work the same way as ELF.
return Base::SelectSectionForGlobal(GO, Kind, TM);
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AVR/AVRTargetObjectFile.h
Expand Up @@ -25,6 +25,11 @@ class AVRTargetObjectFile : public TargetLoweringObjectFileELF {

private:
MCSection *ProgmemDataSection;
MCSection *Progmem1DataSection;
MCSection *Progmem2DataSection;
MCSection *Progmem3DataSection;
MCSection *Progmem4DataSection;
MCSection *Progmem5DataSection;
};

} // end namespace llvm
Expand Down
41 changes: 39 additions & 2 deletions llvm/test/CodeGen/AVR/sections.ll
@@ -1,5 +1,11 @@
; RUN: llc < %s -march=avr | FileCheck --check-prefixes=CHECK,NOSECTIONS %s
; RUN: llc -function-sections -data-sections < %s -march=avr | FileCheck --check-prefixes=CHECK,SECTIONS %s
; RUN: llc < %s -march=avr --mcpu=atxmega384d3 \
; RUN: | FileCheck --check-prefixes=CHECK,NOSECTIONS %s
; RUN: llc -function-sections -data-sections < %s -march=avr --mcpu=atxmega384d3 \
; RUN: | FileCheck --check-prefixes=CHECK,SECTIONS %s
; RUN: not llc -function-sections -data-sections < %s -march=avr --mcpu=at90s8515 2>&1 \
; RUN: | FileCheck --check-prefixes=CHECK-8515 %s
; RUN: not llc -function-sections -data-sections < %s -march=avr --mcpu=attiny40 2>&1 \
; RUN: | FileCheck --check-prefixes=CHECK-tiny40 %s

; Test that functions (in address space 1) are not considered .progmem data.

Expand All @@ -16,10 +22,41 @@ define void @somefunc() addrspace(1) {
; Note: avr-gcc would place this global in .progmem.data.flash with
; -fdata-sections. The AVR backend does not yet respect -fdata-sections in this
; case.

; CHECK: .section .progmem.data,"a",@progbits
; CHECK-LABEL: flash:
@flash = addrspace(1) constant i16 3

; CHECK: .section .progmem1.data,"a",@progbits
; CHECK-LABEL: flash1:
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
@flash1 = addrspace(2) constant i16 4

; CHECK: .section .progmem2.data,"a",@progbits
; CHECK-LABEL: flash2:
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
@flash2 = addrspace(3) constant i16 5

; CHECK: .section .progmem3.data,"a",@progbits
; CHECK-LABEL: flash3:
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
@flash3 = addrspace(4) constant i16 6

; CHECK: .section .progmem4.data,"a",@progbits
; CHECK-LABEL: flash4:
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
@flash4 = addrspace(5) constant i16 7

; CHECK: .section .progmem5.data,"a",@progbits
; CHECK-LABEL: flash5:
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
@flash5 = addrspace(6) constant i16 8

; NOSECTIONS: .section .rodata,"a",@progbits
; SECTIONS: .section .rodata.ram1,"a",@progbits
; CHECK-LABEL: ram1:
Expand Down

0 comments on commit c1dd607

Please sign in to comment.