Index: llvm/include/llvm/MC/MCExpr.h =================================================================== --- llvm/include/llvm/MC/MCExpr.h +++ llvm/include/llvm/MC/MCExpr.h @@ -241,6 +241,7 @@ VK_AVR_DIFF8, VK_AVR_DIFF16, VK_AVR_DIFF32, + VK_AVR_PM, VK_PPC_LO, // symbol@l VK_PPC_HI, // symbol@h Index: llvm/lib/Target/AVR/AVRAsmPrinter.cpp =================================================================== --- llvm/lib/Target/AVR/AVRAsmPrinter.cpp +++ llvm/lib/Target/AVR/AVRAsmPrinter.cpp @@ -15,6 +15,7 @@ #include "AVRMCInstLower.h" #include "AVRSubtarget.h" #include "MCTargetDesc/AVRInstPrinter.h" +#include "MCTargetDesc/AVRMCExpr.h" #include "TargetInfo/AVRTargetInfo.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -53,6 +54,8 @@ void emitInstruction(const MachineInstr *MI) override; + const MCExpr *lowerConstant(const Constant *CV) override; + private: const MCRegisterInfo &MRI; }; @@ -176,6 +179,20 @@ EmitToStreamer(*OutStreamer, I); } +const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV) { + MCContext &Ctx = OutContext; + + if (const GlobalValue *GV = dyn_cast(CV)) { + bool IsFunction = isa(GV); + if (IsFunction) { + const MCExpr *Expr = MCSymbolRefExpr::create(getSymbol(GV), Ctx); + return AVRMCExpr::create(AVRMCExpr::VK_AVR_PM, Expr, false, Ctx); + } + } + + return AsmPrinter::lowerConstant(CV); +} + } // end of namespace llvm extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmPrinter() { Index: llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp =================================================================== --- llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp +++ llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp @@ -8,6 +8,7 @@ #include "MCTargetDesc/AVRFixupKinds.h" #include "MCTargetDesc/AVRMCTargetDesc.h" +#include "MCTargetDesc/AVRMCExpr.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCELFObjectWriter.h" @@ -72,6 +73,7 @@ case MCSymbolRefExpr::VK_None: return ELF::R_AVR_16; case MCSymbolRefExpr::VK_AVR_NONE: + case MCSymbolRefExpr::VK_AVR_PM: return ELF::R_AVR_16_PM; case MCSymbolRefExpr::VK_AVR_DIFF16: return ELF::R_AVR_DIFF16; Index: llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h =================================================================== --- llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h +++ llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h @@ -20,13 +20,14 @@ public: /// Specifies the type of an expression. enum VariantKind { - VK_AVR_None, + VK_AVR_None = 0, VK_AVR_HI8, ///< Corresponds to `hi8()`. VK_AVR_LO8, ///< Corresponds to `lo8()`. VK_AVR_HH8, ///< Corresponds to `hlo8() and hh8()`. VK_AVR_HHI8, ///< Corresponds to `hhi8()`. + VK_AVR_PM, ///< Corresponds to `pm()`, reference to program memory. VK_AVR_PM_LO8, ///< Corresponds to `pm_lo8()`. VK_AVR_PM_HI8, ///< Corresponds to `pm_hi8()`. VK_AVR_PM_HH8, ///< Corresponds to `pm_hh8()`. Index: llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp =================================================================== --- llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp +++ llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp @@ -26,6 +26,7 @@ {"hh8", AVRMCExpr::VK_AVR_HH8}, // synonym with hlo8 {"hlo8", AVRMCExpr::VK_AVR_HH8}, {"hhi8", AVRMCExpr::VK_AVR_HHI8}, + {"pm", AVRMCExpr::VK_AVR_PM}, {"pm_lo8", AVRMCExpr::VK_AVR_PM_LO8}, {"pm_hi8", AVRMCExpr::VK_AVR_PM_HI8}, {"pm_hh8", AVRMCExpr::VK_AVR_PM_HH8}, @@ -87,6 +88,9 @@ MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); if (Modifier != MCSymbolRefExpr::VK_None) return false; + if (Kind == VK_AVR_PM) { + Modifier = MCSymbolRefExpr::VK_AVR_PM; + } Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); Result = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); @@ -131,6 +135,7 @@ Value &= 0xff0000; Value >>= 16; break; + case AVRMCExpr::VK_AVR_PM: case AVRMCExpr::VK_AVR_GS: Value >>= 1; // Program memory addresses must always be shifted by one. break; @@ -167,6 +172,7 @@ case VK_AVR_PM_HH8: Kind = isNegated() ? AVR::fixup_hh8_ldi_pm_neg : AVR::fixup_hh8_ldi_pm; break; + case VK_AVR_PM: case VK_AVR_GS: Kind = AVR::fixup_16_pm; break;