[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