[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