Skip to content

[AVR] Handle flash RO data mapped to data space for newer devices #146244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4886,6 +4886,10 @@ def mguard_EQ : Joined<["-"], "mguard=">, Group<m_Group>,
HelpText<"Enable or disable Control Flow Guard checks and guard tables emission">,
Values<"none,cf,cf-nochecks">;
def mmcu_EQ : Joined<["-"], "mmcu=">, Group<m_Group>;
def mflmap : Flag<["-"], "mflmap">, Group<m_Group>,
HelpText<"Use AVR mapped memory for RO data">;
def mrodata_in_ram : Flag<["-"], "mrodata-in-ram">, Group<m_Group>,
HelpText<"Copy RO data to ram">;
def msim : Flag<["-"], "msim">, Group<m_Group>;
def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group<clang_ignored_m_Group>;
def mieee_fp : Flag<["-"], "mieee-fp">, Group<clang_ignored_m_Group>;
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Basic/Targets/AVR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,10 @@ static MCUInfo AVRMcus[] = {
} // namespace targets
} // namespace clang

static bool ArchHasFLMAP(StringRef Name) {
return Name.starts_with("avr64") || Name.starts_with("avr128");
}

static bool ArchHasELPM(StringRef Arch) {
return llvm::StringSwitch<bool>(Arch)
.Cases("31", "51", "6", true)
Expand Down Expand Up @@ -529,6 +533,8 @@ void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AVR_ARCH__", Arch);

// TODO: perhaps we should use the information from AVRDevices.td instead?
if (ArchHasFLMAP(DefineName))
Builder.defineMacro("__AVR_HAVE_FLMAP__");
if (ArchHasELPM(Arch))
Builder.defineMacro("__AVR_HAVE_ELPM__");
if (ArchHasELPMX(Arch))
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/Driver/ToolChains/AVR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,19 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// This is almost always required because otherwise avr-ld
// will assume 'avr2' and warn about the program being larger
// than the bare minimum supports.
if (Linker.find("avr-ld") != std::string::npos && FamilyName)
CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
if (Linker.find("avr-ld") != std::string::npos && FamilyName) {
// Option to use mapped memory for modern devices with >32kB flash.
// This is the only option for modern devices with <= 32kB flash,
// but the larger default to a copy from flash to RAM (avr-ld version < 14)
// or map the highest 32kB to RAM (avr-ld version >= 14).
if (Args.hasFlag(options::OPT_mflmap, options::OPT_mrodata_in_ram, false)) {
CmdArgs.push_back(
Args.MakeArgString(std::string("-m") + *FamilyName + "_flmap"));
CmdArgs.push_back(Args.MakeArgString(std::string("-u")));
CmdArgs.push_back(Args.MakeArgString(std::string("__do_flmap_init")));
} else
CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
}

C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
Expand Down
14 changes: 10 additions & 4 deletions llvm/lib/Target/AVR/AVRAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,17 @@ bool AVRAsmPrinter::doFinalization(Module &M) {
auto *Section = cast<MCSectionELF>(TLOF.SectionForGlobal(&GO, TM));
if (Section->getName().starts_with(".data"))
NeedsCopyData = true;
else if (Section->getName().starts_with(".rodata") && SubTM->hasLPM())
else if (Section->getName().starts_with(".rodata") && SubTM->hasLPM()) {
// AVRs that have a separate program memory (that's most AVRs) store
// .rodata sections in RAM.
NeedsCopyData = true;
else if (Section->getName().starts_with(".bss"))
// .rodata sections in RAM,
// but XMEGA3 family maps all flash in the data space.
// Invoking __do_copy_data with 0 bytes to copy will crash,
// so we let the loader handle this for newer devices.
if (!(SubTM->hasFeatureSetFamilyXMEGA2() ||
SubTM->hasFeatureSetFamilyXMEGA3() ||
SubTM->hasFeatureSetFamilyXMEGA4()))
NeedsCopyData = true;
} else if (Section->getName().starts_with(".bss"))
NeedsClearBSS = true;
}

Expand Down
56 changes: 34 additions & 22 deletions llvm/lib/Target/AVR/AVRDevices.td
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ def FeatureEIJMPCALL : SubtargetFeature<"eijmpcall", "HasEIJMPCALL", "true",
"The device supports the "
"`EIJMP`/`EICALL` instructions">;

// The device supports `FLMAP` flash bank data mapping to the data space.
def FeatureFLMAP : SubtargetFeature<"flmap", "HasFLMAP", "true",
"The device supports the "
"`FLMAP` mapping">;

// The device maps all flash (<= 32kB) to the data space.
def FeatureMAP : SubtargetFeature<"map", "HasMAP", "true",
"The device maps all flash (<= 32kB) "
"to the data space">;

// The device supports `ADDI Rd, K`, `SUBI Rd, K`.
def FeatureADDSUBIW : SubtargetFeature<"addsubiw", "HasADDSUBIW", "true",
"Enable 16-bit register-immediate "
Expand Down Expand Up @@ -220,6 +230,7 @@ def FamilyXMEGA3 : Family<"xmega3",
[FamilyAVR0, FeatureLPM, FeatureIJMPCALL,
FeatureADDSUBIW, FeatureSRAM, FeatureJMPCALL,
FeatureMultiplication, FeatureMOVW, FeatureLPMX,
FeatureMAP,
FeatureBREAK, FeatureLowByteFirst]>;

def FamilyXMEGA4 : Family<"xmega4",
Expand All @@ -228,6 +239,7 @@ def FamilyXMEGA4 : Family<"xmega4",
FeatureMultiplication, FeatureMOVW, FeatureLPMX,
FeatureELPM, FeatureELPMX,
FeatureSPM, FeatureSPMX,
FeatureFLMAP,
FeatureBREAK, FeatureLowByteFirst]>;

def FamilyXMEGA : Family<"xmega",
Expand Down Expand Up @@ -275,9 +287,9 @@ def : Device<"avr5", FamilyAVR5, ELFArchAVR5>;
def : Device<"avr51", FamilyAVR51, ELFArchAVR51>;
def : Device<"avr6", FamilyAVR6, ELFArchAVR6>;
def : Device<"avrxmega1", FamilyXMEGA, ELFArchXMEGA1>;
def : Device<"avrxmega2", FamilyXMEGA, ELFArchXMEGA2>;
def : Device<"avrxmega2", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avrxmega3", FamilyXMEGA3, ELFArchXMEGA3>;
def : Device<"avrxmega4", FamilyXMEGA, ELFArchXMEGA4>;
def : Device<"avrxmega4", FamilyXMEGA4, ELFArchXMEGA4>;
def : Device<"avrxmega5", FamilyXMEGA, ELFArchXMEGA5>;
def : Device<"avrxmega6", FamilyXMEGA, ELFArchXMEGA6>;
def : Device<"avrxmega7", FamilyXMEGA, ELFArchXMEGA7>;
Expand Down Expand Up @@ -596,26 +608,26 @@ def : Device<"atmega4809", FamilyXMEGA3, ELFArchXMEGA3>;

// Additions from gcc 14:

def : Device<"avr64da28", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64da32", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64da48", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64da64", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64db28", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64db32", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64db48", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64db64", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64dd14", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64dd20", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64dd28", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64dd32", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64du28", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64du32", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64ea28", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64ea32", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64ea48", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64sd28", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64sd32", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64sd48", FamilyXMEGA2, ELFArchXMEGA2>;
def : Device<"avr64da28", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64da32", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64da48", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64da64", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64db28", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64db32", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64db48", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64db64", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64dd14", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64dd20", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64dd28", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64dd32", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64du28", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64du32", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64ea28", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64ea32", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64ea48", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64sd28", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64sd32", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;
def : Device<"avr64sd48", FamilyXMEGA2, ELFArchXMEGA2, [FeatureFLMAP]>;

def : Device<"avr16dd20", FamilyXMEGA3, ELFArchXMEGA3>;
def : Device<"avr16dd28", FamilyXMEGA3, ELFArchXMEGA3>;
Expand Down
Loading