[llvm] 2ccb941 - [AVR] Fix global references to function symbols

Dylan McKay via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 9 03:42:14 PST 2021


Author: Dylan McKay
Date: 2021-02-10T00:40:49+13:00
New Revision: 2ccb941740e608a9cf70a7c5840497149654b0f6

URL: https://github.com/llvm/llvm-project/commit/2ccb941740e608a9cf70a7c5840497149654b0f6
DIFF: https://github.com/llvm/llvm-project/commit/2ccb941740e608a9cf70a7c5840497149654b0f6.diff

LOG: [AVR] Fix global references to function symbols

References to functions are in program memory and need a `pm()` fixup. This should fix trait objects for Rust on AVR.

Differential Revision: https://reviews.llvm.org/D87631

Patch by Alex Mikhalev.

Added: 
    llvm/test/CodeGen/AVR/rust-trait-object.ll

Modified: 
    llvm/include/llvm/MC/MCExpr.h
    llvm/lib/MC/MCExpr.cpp
    llvm/lib/Target/AVR/AVRAsmPrinter.cpp
    llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp
    llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp
    llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h
    llvm/test/MC/AVR/relocations.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 3ffc845e75c0..eb631094ebc4 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -242,6 +242,7 @@ class MCSymbolRefExpr : public MCExpr {
     VK_AVR_DIFF8,
     VK_AVR_DIFF16,
     VK_AVR_DIFF32,
+    VK_AVR_PM,
 
     VK_PPC_LO,              // symbol at l
     VK_PPC_HI,              // symbol at h

diff  --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index 3b123a46d9dc..a18bb2d4a30b 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -269,6 +269,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
   case VK_AVR_DIFF8: return "
diff 8";
   case VK_AVR_DIFF16: return "
diff 16";
   case VK_AVR_DIFF32: return "
diff 32";
+  case VK_AVR_PM: return "pm";
   case VK_PPC_LO: return "l";
   case VK_PPC_HI: return "h";
   case VK_PPC_HA: return "ha";

diff  --git a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
index 722eecdc16a1..e8a13c712210 100644
--- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
+++ b/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 @@ class AVRAsmPrinter : public AsmPrinter {
 
   void emitInstruction(const MachineInstr *MI) override;
 
+  const MCExpr *lowerConstant(const Constant *CV) override;
+
 private:
   const MCRegisterInfo &MRI;
 };
@@ -176,6 +179,20 @@ void AVRAsmPrinter::emitInstruction(const MachineInstr *MI) {
   EmitToStreamer(*OutStreamer, I);
 }
 
+const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV) {
+  MCContext &Ctx = OutContext;
+
+  if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
+    bool IsProgMem = GV->getAddressSpace() == AVR::ProgramMemory;
+    if (IsProgMem) {
+      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() {

diff  --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp
index 1c69fea5962d..bedf68db08ca 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRELFObjectWriter.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "MCTargetDesc/AVRFixupKinds.h"
+#include "MCTargetDesc/AVRMCExpr.h"
 #include "MCTargetDesc/AVRMCTargetDesc.h"
 
 #include "llvm/MC/MCAssembler.h"
@@ -72,6 +73,7 @@ unsigned AVRELFObjectWriter::getRelocType(MCContext &Ctx,
     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;

diff  --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp
index 9eff554a082b..a4f8787e5667 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.cpp
@@ -26,6 +26,7 @@ const struct ModifierEntry {
     {"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 @@ bool AVRMCExpr::evaluateAsRelocatableImpl(MCValue &Result,
     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 @@ int64_t AVRMCExpr::evaluateAsInt64(int64_t Value) const {
     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 @@ AVR::Fixups AVRMCExpr::getFixupKind() const {
   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;

diff  --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h
index 3b696bab1715..e35385ebd90a 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRMCExpr.h
@@ -20,13 +20,14 @@ class AVRMCExpr : public MCTargetExpr {
 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()`.

diff  --git a/llvm/test/CodeGen/AVR/rust-trait-object.ll b/llvm/test/CodeGen/AVR/rust-trait-object.ll
new file mode 100644
index 000000000000..fde89a3b8178
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/rust-trait-object.ll
@@ -0,0 +1,112 @@
+; RUN: llc < %s -march=avr -filetype=asm | FileCheck %s -check-prefix=CHECK-ASM
+; RUN: llc < %s -march=avr -filetype=obj | llvm-objdump -Dr - \
+; RUN:                                   | FileCheck %s -check-prefix=CHECK-OBJ
+
+; Somewhat pruned test case from rustc using trait objects
+
+%TraitObjectA = type {}
+
+; CHECK-ASM-LABEL: vtable.0:
+; CHECK-ASM-NEXT: .short pm(drop_in_place2)
+; CHECK-ASM-NEXT: .short 0
+; CHECK-ASM-NEXT: .short 1
+; CHECK-ASM-NEXT: .short pm(trait_fn2)
+
+; CHECK-OBJ-LABEL: <vtable.0>:
+; CHECK-OBJ-NEXT: 00 00
+; CHECK-OBJ-NEXT: R_AVR_16_PM  .text
+; CHECK-OBJ-NEXT: 00 00
+; CHECK-OBJ-NEXT: 01 00 00 00
+; CHECK-OBJ-NEXT: R_AVR_16_PM  .text
+ at vtable.0 = private constant {
+    void (%TraitObjectA*) addrspace(1)*,
+    i16,
+    i16,
+    i8 (%TraitObjectA*) addrspace(1)*
+  } {
+    void (%TraitObjectA*) addrspace(1)*
+      @drop_in_place2,
+    i16 0,
+    i16 1,
+    i8 (%TraitObjectA*) addrspace(1)*
+      @trait_fn2
+  }, align 1
+
+; CHECK-ASM-LABEL: vtable.1:
+; CHECK-ASM-NEXT: .short pm(drop_in_place1)
+; CHECK-ASM-NEXT: .short 0
+; CHECK-ASM-NEXT: .short 1
+; CHECK-ASM-NEXT: .short pm(trait_fn1)
+
+; CHECK-OBJ-LABEL: <vtable.1>:
+; CHECK-OBJ-NEXT: 00 00
+; CHECK-OBJ-NEXT: R_AVR_16_PM  .text
+; CHECK-OBJ-NEXT: 00 00
+; CHECK-OBJ-NEXT: 01 00 00 00
+; CHECK-OBJ-NEXT: R_AVR_16_PM  .text
+ at vtable.1 = private constant {
+    void (%TraitObjectA*) addrspace(1)*,
+    i16,
+    i16,
+    i8 (%TraitObjectA*) addrspace(1)*
+  } {
+    void (%TraitObjectA*) addrspace(1)*
+      @drop_in_place1,
+    i16 0,
+    i16 1,
+    i8 (%TraitObjectA*) addrspace(1)*
+      @trait_fn1
+  }, align 1
+
+define internal fastcc i8 @TraitObjectA_method(i1 zeroext %choice) addrspace(1) {
+start:
+  %b = alloca %TraitObjectA, align 1
+
+  %c = select i1 %choice, [3 x i16]* bitcast ({
+      void (%TraitObjectA*) addrspace(1)*,
+      i16,
+      i16,
+      i8 (%TraitObjectA*) addrspace(1)*
+    }* @vtable.0 to [3 x i16]*),
+    [3 x i16]* bitcast ({
+      void (%TraitObjectA*) addrspace(1)*,
+      i16,
+      i16,
+      i8 (%TraitObjectA*) addrspace(1)*
+    }* @vtable.1 to [3 x i16]*)
+  %b2 = bitcast %TraitObjectA* %b to {}*
+
+  %res = call fastcc addrspace(1) i8 @call_trait_object({}* nonnull align 1 %b2, [3 x i16]* noalias readonly align 1 dereferenceable(6) %c)
+  ret i8 %res
+}
+
+define internal fastcc i8 @call_trait_object({}* nonnull align 1 %a, [3 x i16]* noalias nocapture readonly align 1 dereferenceable(6) %b) addrspace(1) {
+start:
+  %b2 = getelementptr inbounds [3 x i16], [3 x i16]* %b, i16 0, i16 3
+  %c = bitcast i16* %b2 to i8 ({}*) addrspace(1)**
+  %d = load i8 ({}*) addrspace(1)*, i8 ({}*) addrspace(1)** %c, align 1, !invariant.load !1, !nonnull !1
+  %res = tail call addrspace(1) i8 %d({}* nonnull align 1 %a)
+  ret i8 %res
+}
+
+define internal void @drop_in_place1(%TraitObjectA* nocapture %a) addrspace(1) {
+start:
+  ret void
+}
+
+define internal i8 @trait_fn1(%TraitObjectA* noalias nocapture nonnull readonly align 1 %self) addrspace(1) {
+start:
+  ret i8 89
+}
+
+define internal void @drop_in_place2(%TraitObjectA* nocapture %a) addrspace(1) {
+start:
+  ret void
+}
+
+define internal i8 @trait_fn2(%TraitObjectA* noalias nocapture nonnull readonly align 1 %self) addrspace(1) {
+start:
+  ret i8 79
+}
+
+!1 = !{}

diff  --git a/llvm/test/MC/AVR/relocations.s b/llvm/test/MC/AVR/relocations.s
index 666ff3d30ca4..074823f7c71d 100644
--- a/llvm/test/MC/AVR/relocations.s
+++ b/llvm/test/MC/AVR/relocations.s
@@ -135,12 +135,15 @@ ldi r17, lo8(gs(foo))
 ; CHECK-NEXT: R_AVR_HI8_LDI_GS foo
 ldi r18, hi8(gs(foo))
 
-; CHECK-NEXT: R_AVR_16
+; CHECK-NEXT: R_AVR_16 foo
 .short foo
 
-; CHECK-NEXT: R_AVR_16_PM
+; CHECK-NEXT: R_AVR_16_PM foo
 .short gs(foo)
 
+; CHECK-NEXT: R_AVR_16_PM foo
+.short pm(foo)
+
 ; CHECK-NEXT: R_AVR_8
 .byte foo
 


        


More information about the llvm-commits mailing list