[llvm] c1dd607 - [AVR][MC] Generate section '.progmemX.data' for extended flash banks
Ben Shi via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 19 18:53:28 PST 2022
Author: Ben Shi
Date: 2022-01-20T02:53:10Z
New Revision: c1dd607463dbaa0398df1c88b6759dde03be6353
URL: https://github.com/llvm/llvm-project/commit/c1dd607463dbaa0398df1c88b6759dde03be6353
DIFF: https://github.com/llvm/llvm-project/commit/c1dd607463dbaa0398df1c88b6759dde03be6353.diff
LOG: [AVR][MC] Generate section '.progmemX.data' for extended flash banks
Reviewed By: aykevl
Differential Revision: https://reviews.llvm.org/D115987
Added:
Modified:
llvm/lib/Target/AVR/AVR.h
llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
llvm/lib/Target/AVR/AVRTargetObjectFile.h
llvm/test/CodeGen/AVR/sections.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/AVR/AVR.h b/llvm/lib/Target/AVR/AVR.h
index a21d7d8c63c0a..8c3fd46808149 100644
--- a/llvm/lib/Target/AVR/AVR.h
+++ b/llvm/lib/Target/AVR/AVR.h
@@ -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
diff --git a/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp b/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
index c7715ca1f51be..fe8e863be1a3f 100644
--- a/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
+++ b/llvm/lib/Target/AVR/AVRTargetObjectFile.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "AVRTargetObjectFile.h"
+#include "AVRTargetMachine.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/IR/DerivedTypes.h"
@@ -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);
diff --git a/llvm/lib/Target/AVR/AVRTargetObjectFile.h b/llvm/lib/Target/AVR/AVRTargetObjectFile.h
index 53d8510d9a21d..609849b440295 100644
--- a/llvm/lib/Target/AVR/AVRTargetObjectFile.h
+++ b/llvm/lib/Target/AVR/AVRTargetObjectFile.h
@@ -25,6 +25,11 @@ class AVRTargetObjectFile : public TargetLoweringObjectFileELF {
private:
MCSection *ProgmemDataSection;
+ MCSection *Progmem1DataSection;
+ MCSection *Progmem2DataSection;
+ MCSection *Progmem3DataSection;
+ MCSection *Progmem4DataSection;
+ MCSection *Progmem5DataSection;
};
} // end namespace llvm
diff --git a/llvm/test/CodeGen/AVR/sections.ll b/llvm/test/CodeGen/AVR/sections.ll
index 6d125d37f917e..eff725817be8d 100644
--- a/llvm/test/CodeGen/AVR/sections.ll
+++ b/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.
@@ -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", at progbits
; CHECK-LABEL: flash:
@flash = addrspace(1) constant i16 3
+; CHECK: .section .progmem1.data,"a", at 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
+ at flash1 = addrspace(2) constant i16 4
+
+; CHECK: .section .progmem2.data,"a", at 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
+ at flash2 = addrspace(3) constant i16 5
+
+; CHECK: .section .progmem3.data,"a", at 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
+ at flash3 = addrspace(4) constant i16 6
+
+; CHECK: .section .progmem4.data,"a", at 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
+ at flash4 = addrspace(5) constant i16 7
+
+; CHECK: .section .progmem5.data,"a", at 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
+ at flash5 = addrspace(6) constant i16 8
+
; NOSECTIONS: .section .rodata,"a", at progbits
; SECTIONS: .section .rodata.ram1,"a", at progbits
; CHECK-LABEL: ram1:
More information about the llvm-commits
mailing list