diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp @@ -9,6 +9,7 @@ #include "VEFixupKinds.h" #include "VEMCExpr.h" #include "VEMCTargetDesc.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" @@ -46,16 +47,26 @@ if (IsPCRel) { switch (Fixup.getTargetKind()) { default: - llvm_unreachable("Unimplemented fixup -> relocation"); + Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind"); + return ELF::R_VE_NONE; + case FK_Data_1: case FK_PCRel_1: - llvm_unreachable("Unimplemented fixup fk_data_1 -> relocation"); + Ctx.reportError(Fixup.getLoc(), + "1-byte pc-relative data relocation is not supported"); + return ELF::R_VE_NONE; + case FK_Data_2: case FK_PCRel_2: - llvm_unreachable("Unimplemented fixup fk_data_2 -> relocation"); - // FIXME: relative kind? + Ctx.reportError(Fixup.getLoc(), + "2-byte pc-relative data relocation is not supported"); + return ELF::R_VE_NONE; + case FK_Data_4: case FK_PCRel_4: - return ELF::R_VE_REFLONG; + return ELF::R_VE_SREL32; + case FK_Data_8: case FK_PCRel_8: - return ELF::R_VE_REFQUAD; + Ctx.reportError(Fixup.getLoc(), + "8-byte pc-relative data relocation is not supported"); + return ELF::R_VE_NONE; case VE::fixup_ve_srel32: return ELF::R_VE_SREL32; case VE::fixup_ve_pc_hi32: @@ -67,11 +78,14 @@ switch (Fixup.getTargetKind()) { default: - llvm_unreachable("Unimplemented fixup -> relocation"); + Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type"); + return ELF::R_VE_NONE; case FK_Data_1: - llvm_unreachable("Unimplemented fixup fk_data_1 -> relocation"); + Ctx.reportError(Fixup.getLoc(), "1-byte data relocation is not supported"); + return ELF::R_VE_NONE; case FK_Data_2: - llvm_unreachable("Unimplemented fixup fk_data_2 -> relocation"); + Ctx.reportError(Fixup.getLoc(), "2-byte data relocation is not supported"); + return ELF::R_VE_NONE; case FK_Data_4: return ELF::R_VE_REFLONG; case FK_Data_8: @@ -79,15 +93,21 @@ case VE::fixup_ve_reflong: return ELF::R_VE_REFLONG; case VE::fixup_ve_srel32: - llvm_unreachable("Unimplemented fixup pc_hi32 -> relocation"); + Ctx.reportError(Fixup.getLoc(), + "A non pc-relative srel32 relocation is not supported"); + return ELF::R_VE_NONE; case VE::fixup_ve_hi32: return ELF::R_VE_HI32; case VE::fixup_ve_lo32: return ELF::R_VE_LO32; case VE::fixup_ve_pc_hi32: - llvm_unreachable("Unimplemented fixup pc_hi32 -> relocation"); + Ctx.reportError(Fixup.getLoc(), + "A non pc-relative pc_hi32 relocation is not supported"); + return ELF::R_VE_NONE; case VE::fixup_ve_pc_lo32: - llvm_unreachable("Unimplemented fixup pc_lo32 -> relocation"); + Ctx.reportError(Fixup.getLoc(), + "A non pc-relative pc_lo32 relocation is not supported"); + return ELF::R_VE_NONE; case VE::fixup_ve_got_hi32: return ELF::R_VE_GOT_HI32; case VE::fixup_ve_got_lo32: diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp @@ -102,11 +102,11 @@ const MCSubtargetInfo &STI) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); - if (MO.isImm()) - return MO.getImm(); + return static_cast(MO.getImm()); assert(MO.isExpr()); + const MCExpr *Expr = MO.getExpr(); if (const VEMCExpr *SExpr = dyn_cast(Expr)) { MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind(); diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp --- a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp +++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp @@ -12,11 +12,12 @@ //===----------------------------------------------------------------------===// #include "VEMCExpr.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSymbolELF.h" -#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCValue.h" using namespace llvm; @@ -174,7 +175,13 @@ bool VEMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); + if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) + return false; + + Res = + MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); + + return true; } static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { diff --git a/llvm/test/MC/VE/data-reloc-error.s b/llvm/test/MC/VE/data-reloc-error.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/VE/data-reloc-error.s @@ -0,0 +1,26 @@ +# RUN: not llvm-mc -filetype=obj -triple=ve %s -o /dev/null 2>&1 | \ +# RUN: FileCheck %s +# RUN: not llvm-mc -filetype=obj -triple=ve -position-independent %s \ +# RUN: -o /dev/null 2>&1 | FileCheck %s + +.data +a: +## An undefined reference of _GLOBAL_OFFSET_TABLE_ causes .got[0] to be +## allocated to store _DYNAMIC. +.byte _GLOBAL_OFFSET_TABLE_ +.byte _GLOBAL_OFFSET_TABLE_ - . +.2byte _GLOBAL_OFFSET_TABLE_ +.2byte _GLOBAL_OFFSET_TABLE_ - . +.8byte _GLOBAL_OFFSET_TABLE_ - . + +# CHECK: data-reloc-error.s:10:7: error: 1-byte data relocation is not supported +# CHECK-NEXT: .byte _GLOBAL_OFFSET_TABLE_ +# CHECK: data-reloc-error.s:11:7: error: 1-byte pc-relative data relocation is not supported +# CHECK-NEXT: .byte _GLOBAL_OFFSET_TABLE_ - . +# CHECK: data-reloc-error.s:12:8: error: 2-byte data relocation is not supported +# CHECK-NEXT: .2byte _GLOBAL_OFFSET_TABLE_ +# CHECK: data-reloc-error.s:13:8: error: 2-byte pc-relative data relocation is not supported +# CHECK-NEXT: .2byte _GLOBAL_OFFSET_TABLE_ - . +# CHECK: data-reloc-error.s:14:8: error: 8-byte pc-relative data relocation is not supported +# CHECK-NEXT: .8byte _GLOBAL_OFFSET_TABLE_ - . + diff --git a/llvm/test/MC/VE/data-reloc.s b/llvm/test/MC/VE/data-reloc.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/VE/data-reloc.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | \ +# RUN: llvm-objdump -r - | FileCheck %s +# RUN: llvm-mc -triple=ve -filetype=obj -position-independent %s -o - | \ +# RUN: llvm-objdump -r - | FileCheck %s + +.data +a: +## An undefined reference of _GLOBAL_OFFSET_TABLE_ causes .got[0] to be +## allocated to store _DYNAMIC. +.4byte _GLOBAL_OFFSET_TABLE_ - 8 +.4byte _GLOBAL_OFFSET_TABLE_ - . - 8 +.8byte _GLOBAL_OFFSET_TABLE_ - 8 + +# CHECK: 0000000000000000 R_VE_REFLONG _GLOBAL_OFFSET_TABLE_-0x8 +# CHECK: 0000000000000004 R_VE_SREL32 _GLOBAL_OFFSET_TABLE_-0x8 +# CHECK: 0000000000000008 R_VE_REFQUAD _GLOBAL_OFFSET_TABLE_-0x8