Skip to content

Commit c1dd607

Browse files
committed
[AVR][MC] Generate section '.progmemX.data' for extended flash banks
Reviewed By: aykevl Differential Revision: https://reviews.llvm.org/D115987
1 parent 34570f4 commit c1dd607

File tree

4 files changed

+125
-10
lines changed

4 files changed

+125
-10
lines changed

llvm/lib/Target/AVR/AVR.h

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,43 @@ void initializeAVRRelaxMemPass(PassRegistry &);
3838
namespace AVR {
3939

4040
/// An integer that identifies all of the supported AVR address spaces.
41-
enum AddressSpace { DataMemory, ProgramMemory };
41+
enum AddressSpace {
42+
DataMemory,
43+
ProgramMemory,
44+
ProgramMemory1,
45+
ProgramMemory2,
46+
ProgramMemory3,
47+
ProgramMemory4,
48+
ProgramMemory5,
49+
NumAddrSpaces,
50+
};
4251

4352
/// Checks if a given type is a pointer to program memory.
4453
template <typename T> bool isProgramMemoryAddress(T *V) {
45-
return cast<PointerType>(V->getType())->getAddressSpace() == ProgramMemory;
54+
auto *PT = cast<PointerType>(V->getType());
55+
assert(PT != nullptr && "unexpected MemSDNode");
56+
return PT->getAddressSpace() == ProgramMemory ||
57+
PT->getAddressSpace() == ProgramMemory1 ||
58+
PT->getAddressSpace() == ProgramMemory2 ||
59+
PT->getAddressSpace() == ProgramMemory3 ||
60+
PT->getAddressSpace() == ProgramMemory4 ||
61+
PT->getAddressSpace() == ProgramMemory5;
4662
}
4763

48-
inline bool isProgramMemoryAccess(MemSDNode const *N) {
49-
auto V = N->getMemOperand()->getValue();
64+
template <typename T> AddressSpace getAddressSpace(T *V) {
65+
auto *PT = cast<PointerType>(V->getType());
66+
assert(PT != nullptr && "unexpected MemSDNode");
67+
unsigned AS = PT->getAddressSpace();
68+
if (AS < NumAddrSpaces)
69+
return static_cast<AddressSpace>(AS);
70+
return NumAddrSpaces;
71+
}
5072

51-
return (V != nullptr) ? isProgramMemoryAddress(V) : false;
73+
inline bool isProgramMemoryAccess(MemSDNode const *N) {
74+
auto *V = N->getMemOperand()->getValue();
75+
if (V != nullptr && isProgramMemoryAddress(V))
76+
return true;
77+
return false;
5278
}
5379

5480
} // end of namespace AVR

llvm/lib/Target/AVR/AVRTargetObjectFile.cpp

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "AVRTargetObjectFile.h"
10+
#include "AVRTargetMachine.h"
1011

1112
#include "llvm/BinaryFormat/ELF.h"
1213
#include "llvm/IR/DerivedTypes.h"
@@ -22,14 +23,60 @@ void AVRTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM) {
2223
Base::Initialize(Ctx, TM);
2324
ProgmemDataSection =
2425
Ctx.getELFSection(".progmem.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
26+
Progmem1DataSection =
27+
Ctx.getELFSection(".progmem1.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
28+
Progmem2DataSection =
29+
Ctx.getELFSection(".progmem2.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
30+
Progmem3DataSection =
31+
Ctx.getELFSection(".progmem3.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
32+
Progmem4DataSection =
33+
Ctx.getELFSection(".progmem4.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
34+
Progmem5DataSection =
35+
Ctx.getELFSection(".progmem5.data", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
2536
}
2637

2738
MCSection *AVRTargetObjectFile::SelectSectionForGlobal(
2839
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
29-
// Global values in flash memory are placed in the progmem.data section
40+
// Global values in flash memory are placed in the progmem*.data section
3041
// unless they already have a user assigned section.
31-
if (AVR::isProgramMemoryAddress(GO) && !GO->hasSection() && Kind.isReadOnly())
32-
return ProgmemDataSection;
42+
const auto &AVRTM = static_cast<const AVRTargetMachine &>(TM);
43+
if (AVR::isProgramMemoryAddress(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+
SMLoc(),
50+
"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(GO) != AVR::ProgramMemory) {
57+
// TODO: Get the global object's location in source file.
58+
getContext().reportError(SMLoc(),
59+
"Current AVR subtarget does not support "
60+
"accessing extended program memory");
61+
return ProgmemDataSection;
62+
}
63+
switch (AVR::getAddressSpace(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+
}
3380

3481
// Otherwise, we work the same way as ELF.
3582
return Base::SelectSectionForGlobal(GO, Kind, TM);

llvm/lib/Target/AVR/AVRTargetObjectFile.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ class AVRTargetObjectFile : public TargetLoweringObjectFileELF {
2525

2626
private:
2727
MCSection *ProgmemDataSection;
28+
MCSection *Progmem1DataSection;
29+
MCSection *Progmem2DataSection;
30+
MCSection *Progmem3DataSection;
31+
MCSection *Progmem4DataSection;
32+
MCSection *Progmem5DataSection;
2833
};
2934

3035
} // end namespace llvm

llvm/test/CodeGen/AVR/sections.ll

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
; RUN: llc < %s -march=avr | FileCheck --check-prefixes=CHECK,NOSECTIONS %s
2-
; RUN: llc -function-sections -data-sections < %s -march=avr | FileCheck --check-prefixes=CHECK,SECTIONS %s
1+
; RUN: llc < %s -march=avr --mcpu=atxmega384d3 \
2+
; RUN: | FileCheck --check-prefixes=CHECK,NOSECTIONS %s
3+
; RUN: llc -function-sections -data-sections < %s -march=avr --mcpu=atxmega384d3 \
4+
; RUN: | FileCheck --check-prefixes=CHECK,SECTIONS %s
5+
; RUN: not llc -function-sections -data-sections < %s -march=avr --mcpu=at90s8515 2>&1 \
6+
; RUN: | FileCheck --check-prefixes=CHECK-8515 %s
7+
; RUN: not llc -function-sections -data-sections < %s -march=avr --mcpu=attiny40 2>&1 \
8+
; RUN: | FileCheck --check-prefixes=CHECK-tiny40 %s
39

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

@@ -16,10 +22,41 @@ define void @somefunc() addrspace(1) {
1622
; Note: avr-gcc would place this global in .progmem.data.flash with
1723
; -fdata-sections. The AVR backend does not yet respect -fdata-sections in this
1824
; case.
25+
1926
; CHECK: .section .progmem.data,"a",@progbits
2027
; CHECK-LABEL: flash:
2128
@flash = addrspace(1) constant i16 3
2229

30+
; CHECK: .section .progmem1.data,"a",@progbits
31+
; CHECK-LABEL: flash1:
32+
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
33+
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
34+
@flash1 = addrspace(2) constant i16 4
35+
36+
; CHECK: .section .progmem2.data,"a",@progbits
37+
; CHECK-LABEL: flash2:
38+
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
39+
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
40+
@flash2 = addrspace(3) constant i16 5
41+
42+
; CHECK: .section .progmem3.data,"a",@progbits
43+
; CHECK-LABEL: flash3:
44+
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
45+
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
46+
@flash3 = addrspace(4) constant i16 6
47+
48+
; CHECK: .section .progmem4.data,"a",@progbits
49+
; CHECK-LABEL: flash4:
50+
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
51+
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
52+
@flash4 = addrspace(5) constant i16 7
53+
54+
; CHECK: .section .progmem5.data,"a",@progbits
55+
; CHECK-LABEL: flash5:
56+
; CHECK-8515: error: Current AVR subtarget does not support accessing extended program memory
57+
; CHECK-tiny40: error: Current AVR subtarget does not support accessing program memory
58+
@flash5 = addrspace(6) constant i16 8
59+
2360
; NOSECTIONS: .section .rodata,"a",@progbits
2461
; SECTIONS: .section .rodata.ram1,"a",@progbits
2562
; CHECK-LABEL: ram1:

0 commit comments

Comments
 (0)