dylanmckay created this revision. dylanmckay added a reviewer: aykevl. Herald added a subscriber: Jim. Herald added a project: clang. dylanmckay requested review of this revision.
This patch modifies the Clang AVR toolchain so that it always passes the '-Tdata=0x800100' to the linker for ATmega328 devices. This matches AVR-GCC behaviour, and also corresponds to the address of the start of the data section in data space according to the ATmega328 datasheet. Without this, clang does not produce a valid ATmega328 binary. When targeting all non-ATmega328 chips, a warning will be emitted due to the fact that proper handling for the chips data section address is not yet implemented. I've held off adding other microcontrollers for now, mostly because the AVR toolchain logic is smeared across LLVM core TableGen files, and two Clang libraries. The 'family detection' logic is also only implemented for ATmega328 at the moment, for similar reasons. In the future, I aim to write an RFC to llvm-dev to find a better way for LLVM to expose target-specific details such as these to compiler frontends. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D86629 Files: clang/include/clang/Basic/DiagnosticDriverKinds.td clang/lib/Driver/ToolChains/AVR.cpp Index: clang/lib/Driver/ToolChains/AVR.cpp =================================================================== --- clang/lib/Driver/ToolChains/AVR.cpp +++ clang/lib/Driver/ToolChains/AVR.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/SubtargetFeature.h" @@ -36,6 +37,13 @@ .Default(Optional<StringRef>()); } +llvm::Optional<unsigned> GetMcuSectionAddressData(StringRef MCU) { + return llvm::StringSwitch<llvm::Optional<unsigned>>(MCU) + .Case("atmega328", Optional<unsigned>(0x800100)) + .Case("atmega328p", Optional<unsigned>(0x800100)) + .Default(Optional<unsigned>()); +} + const StringRef PossibleAVRLibcLocations[] = { "/usr/avr", "/usr/lib/avr", @@ -103,6 +111,7 @@ // Compute information about the target AVR. std::string CPU = getCPUName(Args, getToolChain().getTriple()); llvm::Optional<StringRef> FamilyName = GetMcuFamilyName(CPU); + llvm::Optional<unsigned> SectionAddressData = GetMcuSectionAddressData(CPU); std::string Linker = getToolChain().GetProgramPath(getShortName()); ArgStringList CmdArgs; @@ -118,6 +127,17 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); getToolChain().AddFilePathLibArgs(Args, CmdArgs); + if (SectionAddressData.hasValue()) { + std::string DataSectionArg = std::string("-Tdata=0x") + + llvm::utohexstr(SectionAddressData.getValue()); + CmdArgs.push_back(Args.MakeArgString(DataSectionArg)); + } else { + // We do not have an entry for this CPU in the address mapping table yet. + getToolChain().getDriver().Diag( + diag::warn_drv_avr_linker_section_addresses_not_implemented) + << CPU; + } + // If the family name is known, we can link with the device-specific libgcc. // Without it, libgcc will simply not be linked. This matches avr-gcc // behavior. Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -44,6 +44,10 @@ def warn_drv_avr_family_linking_stdlibs_not_implemented: Warning< "support for linking stdlibs for microcontroller '%0' is not implemented">, InGroup<AVRRtlibLinkingQuirks>; +def warn_drv_avr_linker_section_addresses_not_implemented: Warning< + "support for passing the data section address to the linker for " + "microcontroller '%0' is not implemented">, + InGroup<AVRRtlibLinkingQuirks>; def warn_drv_avr_stdlib_not_linked: Warning< "standard library not linked and so no interrupt vector table or " "compiler runtime routines will be linked">,
Index: clang/lib/Driver/ToolChains/AVR.cpp =================================================================== --- clang/lib/Driver/ToolChains/AVR.cpp +++ clang/lib/Driver/ToolChains/AVR.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/SubtargetFeature.h" @@ -36,6 +37,13 @@ .Default(Optional<StringRef>()); } +llvm::Optional<unsigned> GetMcuSectionAddressData(StringRef MCU) { + return llvm::StringSwitch<llvm::Optional<unsigned>>(MCU) + .Case("atmega328", Optional<unsigned>(0x800100)) + .Case("atmega328p", Optional<unsigned>(0x800100)) + .Default(Optional<unsigned>()); +} + const StringRef PossibleAVRLibcLocations[] = { "/usr/avr", "/usr/lib/avr", @@ -103,6 +111,7 @@ // Compute information about the target AVR. std::string CPU = getCPUName(Args, getToolChain().getTriple()); llvm::Optional<StringRef> FamilyName = GetMcuFamilyName(CPU); + llvm::Optional<unsigned> SectionAddressData = GetMcuSectionAddressData(CPU); std::string Linker = getToolChain().GetProgramPath(getShortName()); ArgStringList CmdArgs; @@ -118,6 +127,17 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); getToolChain().AddFilePathLibArgs(Args, CmdArgs); + if (SectionAddressData.hasValue()) { + std::string DataSectionArg = std::string("-Tdata=0x") + + llvm::utohexstr(SectionAddressData.getValue()); + CmdArgs.push_back(Args.MakeArgString(DataSectionArg)); + } else { + // We do not have an entry for this CPU in the address mapping table yet. + getToolChain().getDriver().Diag( + diag::warn_drv_avr_linker_section_addresses_not_implemented) + << CPU; + } + // If the family name is known, we can link with the device-specific libgcc. // Without it, libgcc will simply not be linked. This matches avr-gcc // behavior. Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -44,6 +44,10 @@ def warn_drv_avr_family_linking_stdlibs_not_implemented: Warning< "support for linking stdlibs for microcontroller '%0' is not implemented">, InGroup<AVRRtlibLinkingQuirks>; +def warn_drv_avr_linker_section_addresses_not_implemented: Warning< + "support for passing the data section address to the linker for " + "microcontroller '%0' is not implemented">, + InGroup<AVRRtlibLinkingQuirks>; def warn_drv_avr_stdlib_not_linked: Warning< "standard library not linked and so no interrupt vector table or " "compiler runtime routines will be linked">,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits