[llvm] e026f14 - [VE] Support relocation information in MC layer

Simon Moll via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 15 02:25:12 PDT 2020


Author: Kazushi (Jam) Marukawa
Date: 2020-06-15T11:24:53+02:00
New Revision: e026f147f7b412aec4511b5b00757671ee95a219

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

LOG: [VE] Support relocation information in MC layer

Summary:
Change VEAsmParser to support identification with relocation information
in assmebler.  Change VEAsmBackend to support relocation information in
MC layer.  Change VEDisassembler and VEMCCodeEmitter to support binary
generation of branch target operands.  Add REFLONG fixup and variant kind
to support new R_VE_REFLONG ELF symbol.  And, add regression test in both
MC and CodeGen to check binary genaration with relocation information.

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

Added: 
    llvm/test/CodeGen/VE/symbol_relocation.ll
    llvm/test/CodeGen/VE/symbol_relocation_tls.ll
    llvm/test/MC/VE/sym-got.s
    llvm/test/MC/VE/sym-gotoff.s
    llvm/test/MC/VE/sym-tls.s
    llvm/test/MC/VE/sym-tpoff.s
    llvm/test/MC/VE/symbols.s

Modified: 
    llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
    llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
    llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
    llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
    llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
    llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
    llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
    llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
    llvm/lib/Target/VE/VEInstrInfo.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
index dcdcef606d5c..214adf4c3c5b 100644
--- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
+++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
@@ -65,6 +65,8 @@ class VEAsmParser : public MCTargetAsmParser {
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
 
+  // Helper function to parse and generate identifier with relocation.
+  const MCExpr *parseIdentifier(StringRef Identifier);
   // Custom parse functions for VE specific operands.
   OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
   OperandMatchResultTy parseMEMAsOperand(OperandVector &Operands);
@@ -946,6 +948,29 @@ bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
   return true;
 }
 
+const MCExpr *VEAsmParser::parseIdentifier(StringRef Identifier) {
+  StringRef Modifier;
+  // Search @modifiers like "symbol at hi".
+  size_t at = Identifier.rfind('@');
+  if (at != 0 || at != StringRef::npos) {
+    std::pair<StringRef, StringRef> Pair = Identifier.rsplit("@");
+    if (!Pair.first.empty() && !Pair.second.empty()) {
+      Identifier = Pair.first;
+      Modifier = Pair.second;
+    }
+  }
+  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
+  const MCExpr *Res =
+      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+  VEMCExpr::VariantKind VK = VEMCExpr::parseVariantKind(Modifier);
+  if (VK == VEMCExpr::VK_VE_None) {
+    // Create identifier using default variant kind
+    VEMCExpr::VariantKind Kind = VEMCExpr::VK_VE_REFLONG;
+    return VEMCExpr::create(Kind, Res, getContext());
+  }
+  return VEMCExpr::create(VK, Res, getContext());
+}
+
 OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
   LLVM_DEBUG(dbgs() << "parseMEMOperand\n");
   const AsmToken &Tok = Parser.getTok();
@@ -975,6 +1000,19 @@ OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
       return MatchOperand_NoMatch;
     break;
   }
+
+  case AsmToken::Identifier: {
+    StringRef Identifier;
+    if (!getParser().parseIdentifier(Identifier)) {
+      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+      const MCExpr *EVal = parseIdentifier(Identifier);
+
+      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+      Offset = VEOperand::CreateImm(EVal, S, E);
+    }
+    break;
+  }
+
   case AsmToken::LParen:
     // empty disp (= 0)
     Offset =

diff  --git a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
index 6524cd12a9f9..35885a4e3cae 100644
--- a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
+++ b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp
@@ -187,6 +187,8 @@ static DecodeStatus DecodeCall(MCInst &Inst, uint64_t insn, uint64_t Address,
                                const void *Decoder);
 static DecodeStatus DecodeSIMM7(MCInst &Inst, uint64_t insn, uint64_t Address,
                                 const void *Decoder);
+static DecodeStatus DecodeSIMM32(MCInst &Inst, uint64_t insn, uint64_t Address,
+                                 const void *Decoder);
 static DecodeStatus DecodeCCOperand(MCInst &Inst, uint64_t insn,
                                     uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeRDOperand(MCInst &Inst, uint64_t insn,
@@ -468,6 +470,13 @@ static DecodeStatus DecodeSIMM7(MCInst &MI, uint64_t insn, uint64_t Address,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeSIMM32(MCInst &MI, uint64_t insn, uint64_t Address,
+                                 const void *Decoder) {
+  uint64_t tgt = SignExtend64<32>(insn);
+  MI.addOperand(MCOperand::createImm(tgt));
+  return MCDisassembler::Success;
+}
+
 static bool isIntegerBCKind(MCInst &MI) {
 
 #define BCm_kind(NAME)                                                         \

diff  --git a/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
index dcc9fe8f7e4a..9a6ae90b5c73 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
@@ -24,6 +24,68 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
   switch (Kind) {
   default:
     llvm_unreachable("Unknown fixup kind!");
+  case FK_Data_1:
+  case FK_Data_2:
+  case FK_Data_4:
+  case FK_Data_8:
+  case FK_PCRel_1:
+  case FK_PCRel_2:
+  case FK_PCRel_4:
+  case FK_PCRel_8:
+    return Value;
+  case VE::fixup_ve_hi32:
+  case VE::fixup_ve_pc_hi32:
+  case VE::fixup_ve_got_hi32:
+  case VE::fixup_ve_gotoff_hi32:
+  case VE::fixup_ve_plt_hi32:
+  case VE::fixup_ve_tls_gd_hi32:
+  case VE::fixup_ve_tpoff_hi32:
+    return (Value >> 32) & 0xffffffff;
+  case VE::fixup_ve_reflong:
+  case VE::fixup_ve_lo32:
+  case VE::fixup_ve_pc_lo32:
+  case VE::fixup_ve_got_lo32:
+  case VE::fixup_ve_gotoff_lo32:
+  case VE::fixup_ve_plt_lo32:
+  case VE::fixup_ve_tls_gd_lo32:
+  case VE::fixup_ve_tpoff_lo32:
+    return Value & 0xffffffff;
+  }
+}
+
+/// getFixupKindNumBytes - The number of bytes the fixup may change.
+static unsigned getFixupKindNumBytes(unsigned Kind) {
+  switch (Kind) {
+  default:
+    llvm_unreachable("Unknown fixup kind!");
+  case FK_Data_1:
+  case FK_PCRel_1:
+    return 1;
+  case FK_Data_2:
+  case FK_PCRel_2:
+    return 2;
+    return 4;
+  case FK_Data_4:
+  case FK_PCRel_4:
+  case VE::fixup_ve_reflong:
+  case VE::fixup_ve_hi32:
+  case VE::fixup_ve_lo32:
+  case VE::fixup_ve_pc_hi32:
+  case VE::fixup_ve_pc_lo32:
+  case VE::fixup_ve_got_hi32:
+  case VE::fixup_ve_got_lo32:
+  case VE::fixup_ve_gotoff_hi32:
+  case VE::fixup_ve_gotoff_lo32:
+  case VE::fixup_ve_plt_hi32:
+  case VE::fixup_ve_plt_lo32:
+  case VE::fixup_ve_tls_gd_hi32:
+  case VE::fixup_ve_tls_gd_lo32:
+  case VE::fixup_ve_tpoff_hi32:
+  case VE::fixup_ve_tpoff_lo32:
+    return 4;
+  case FK_Data_8:
+  case FK_PCRel_8:
+    return 8;
   }
 }
 
@@ -38,22 +100,51 @@ class VEAsmBackend : public MCAsmBackend {
   unsigned getNumFixupKinds() const override { return VE::NumTargetFixupKinds; }
 
   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
+    const static MCFixupKindInfo Infos[VE::NumTargetFixupKinds] = {
+        // name, offset, bits, flags
+        {"fixup_ve_reflong", 0, 32, 0},
+        {"fixup_ve_hi32", 0, 32, 0},
+        {"fixup_ve_lo32", 0, 32, 0},
+        {"fixup_ve_pc_hi32", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+        {"fixup_ve_pc_lo32", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
+        {"fixup_ve_got_hi32", 0, 32, 0},
+        {"fixup_ve_got_lo32", 0, 32, 0},
+        {"fixup_ve_gotoff_hi32", 0, 32, 0},
+        {"fixup_ve_gotoff_lo32", 0, 32, 0},
+        {"fixup_ve_plt_hi32", 0, 32, 0},
+        {"fixup_ve_plt_lo32", 0, 32, 0},
+        {"fixup_ve_tls_gd_hi32", 0, 32, 0},
+        {"fixup_ve_tls_gd_lo32", 0, 32, 0},
+        {"fixup_ve_tpoff_hi32", 0, 32, 0},
+        {"fixup_ve_tpoff_lo32", 0, 32, 0},
+    };
+
     if (Kind < FirstTargetFixupKind)
       return MCAsmBackend::getFixupKindInfo(Kind);
 
-    // FIXME.
-    llvm_unreachable("getFixupKindInfo() unimplemented");
+    assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+           "Invalid kind!");
+    return Infos[Kind - FirstTargetFixupKind];
   }
 
   bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
                              const MCValue &Target) override {
-    // FIXME.
-    return false;
+    switch ((VE::Fixups)Fixup.getKind()) {
+    default:
+      return false;
+    case VE::fixup_ve_tls_gd_hi32:
+    case VE::fixup_ve_tls_gd_lo32:
+    case VE::fixup_ve_tpoff_hi32:
+    case VE::fixup_ve_tpoff_lo32:
+      return true;
+    }
   }
 
   bool mayNeedRelaxation(const MCInst &Inst,
                          const MCSubtargetInfo &STI) const override {
-    // FIXME.
+    // Not implemented yet.  For example, if we have a branch with
+    // lager than SIMM32 immediate value, we want to relaxation such
+    // branch instructions.
     return false;
   }
 
@@ -62,14 +153,15 @@ class VEAsmBackend : public MCAsmBackend {
   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
                             const MCRelaxableFragment *DF,
                             const MCAsmLayout &Layout) const override {
-    // FIXME.
-    llvm_unreachable("fixupNeedsRelaxation() unimplemented");
+    // Not implemented yet.  For example, if we have a branch with
+    // lager than SIMM32 immediate value, we want to relaxation such
+    // branch instructions.
     return false;
   }
   void relaxInstruction(MCInst &Inst,
                         const MCSubtargetInfo &STI) const override {
-    // FIXME.
-    llvm_unreachable("relaxInstruction() unimplemented");
+    // Aurora VE doesn't support relaxInstruction yet.
+    llvm_unreachable("relaxInstruction() should not be called");
   }
 
   bool writeNopData(raw_ostream &OS, uint64_t Count) const override {
@@ -99,8 +191,21 @@ class ELFVEAsmBackend : public VEAsmBackend {
     if (!Value)
       return; // Doesn't change encoding.
 
-    // FIXME.
-    llvm_unreachable("applyFixup() unimplemented");
+    MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
+
+    // Shift the value into position.
+    Value <<= Info.TargetOffset;
+
+    unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
+    unsigned Offset = Fixup.getOffset();
+    assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
+    // For each byte of the fragment that the fixup touches, mask in the bits
+    // from the fixup value. The Value has been "split up" into the
+    // appropriate bitfields above.
+    for (unsigned i = 0; i != NumBytes; ++i) {
+      unsigned Idx = Endian == support::little ? i : (NumBytes - 1) - i;
+      Data[Offset + Idx] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
+    }
   }
 
   std::unique_ptr<MCObjectTargetWriter>
@@ -109,7 +214,6 @@ class ELFVEAsmBackend : public VEAsmBackend {
     return createVEELFObjectWriter(OSABI);
   }
 };
-
 } // end anonymous namespace
 
 MCAsmBackend *llvm::createVEAsmBackend(const Target &T,

diff  --git a/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
index 77ac97979cef..741e8320a941 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "VEFixupKinds.h"
+#include "VEMCExpr.h"
 #include "VEMCTargetDesc.h"
 #include "llvm/MC/MCELFObjectWriter.h"
 #include "llvm/MC/MCExpr.h"
@@ -37,14 +38,95 @@ class VEELFObjectWriter : public MCELFObjectTargetWriter {
 unsigned VEELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
                                          const MCFixup &Fixup,
                                          bool IsPCRel) const {
-  // FIXME: implements.
+  if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Fixup.getValue())) {
+    if (SExpr->getKind() == VEMCExpr::VK_VE_PC_LO32)
+      return ELF::R_VE_PC_LO32;
+  }
+
+  if (IsPCRel) {
+    switch (Fixup.getTargetKind()) {
+    default:
+      llvm_unreachable("Unimplemented fixup -> relocation");
+    case FK_PCRel_1:
+      llvm_unreachable("Unimplemented fixup fk_data_1 -> relocation");
+    case FK_PCRel_2:
+      llvm_unreachable("Unimplemented fixup fk_data_2 -> relocation");
+    // FIXME: relative kind?
+    case FK_PCRel_4:
+      return ELF::R_VE_REFLONG;
+    case FK_PCRel_8:
+      return ELF::R_VE_REFQUAD;
+    case VE::fixup_ve_pc_hi32:
+      return ELF::R_VE_PC_HI32;
+    case VE::fixup_ve_pc_lo32:
+      return ELF::R_VE_PC_LO32;
+    }
+  }
+
+  switch (Fixup.getTargetKind()) {
+  default:
+    llvm_unreachable("Unimplemented fixup -> relocation");
+  case FK_Data_1:
+    llvm_unreachable("Unimplemented fixup fk_data_1 -> relocation");
+  case FK_Data_2:
+    llvm_unreachable("Unimplemented fixup fk_data_2 -> relocation");
+  case FK_Data_4:
+    return ELF::R_VE_REFLONG;
+  case FK_Data_8:
+    return ELF::R_VE_REFQUAD;
+  case VE::fixup_ve_reflong:
+    return ELF::R_VE_REFLONG;
+  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");
+  case VE::fixup_ve_pc_lo32:
+    llvm_unreachable("Unimplemented fixup pc_lo32 -> relocation");
+  case VE::fixup_ve_got_hi32:
+    return ELF::R_VE_GOT_HI32;
+  case VE::fixup_ve_got_lo32:
+    return ELF::R_VE_GOT_LO32;
+  case VE::fixup_ve_gotoff_hi32:
+    return ELF::R_VE_GOTOFF_HI32;
+  case VE::fixup_ve_gotoff_lo32:
+    return ELF::R_VE_GOTOFF_LO32;
+  case VE::fixup_ve_plt_hi32:
+    return ELF::R_VE_PLT_HI32;
+  case VE::fixup_ve_plt_lo32:
+    return ELF::R_VE_PLT_LO32;
+  case VE::fixup_ve_tls_gd_hi32:
+    return ELF::R_VE_TLS_GD_HI32;
+  case VE::fixup_ve_tls_gd_lo32:
+    return ELF::R_VE_TLS_GD_LO32;
+  case VE::fixup_ve_tpoff_hi32:
+    return ELF::R_VE_TPOFF_HI32;
+  case VE::fixup_ve_tpoff_lo32:
+    return ELF::R_VE_TPOFF_LO32;
+  }
+
   return ELF::R_VE_NONE;
 }
 
 bool VEELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
                                                 unsigned Type) const {
-  // FIXME: implements.
-  return false;
+  switch (Type) {
+  default:
+    return false;
+
+  // All relocations that use a GOT need a symbol, not an offset, as
+  // the offset of the symbol within the section is irrelevant to
+  // where the GOT entry is. Don't need to list all the TLS entries,
+  // as they're all marked as requiring a symbol anyways.
+  case ELF::R_VE_GOT_HI32:
+  case ELF::R_VE_GOT_LO32:
+  case ELF::R_VE_GOTOFF_HI32:
+  case ELF::R_VE_GOTOFF_LO32:
+  case ELF::R_VE_TLS_GD_HI32:
+  case ELF::R_VE_TLS_GD_LO32:
+    return true;
+  }
 }
 
 std::unique_ptr<MCObjectTargetWriter>

diff  --git a/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h b/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
index 46a340f95d97..5d5dc1c5c891 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEFixupKinds.h
@@ -14,8 +14,11 @@
 namespace llvm {
 namespace VE {
 enum Fixups {
+  /// fixup_ve_reflong - 32-bit fixup corresponding to foo
+  fixup_ve_reflong = FirstTargetFixupKind,
+
   /// fixup_ve_hi32 - 32-bit fixup corresponding to foo at hi
-  fixup_ve_hi32 = FirstTargetFixupKind,
+  fixup_ve_hi32,
 
   /// fixup_ve_lo32 - 32-bit fixup corresponding to foo at lo
   fixup_ve_lo32,

diff  --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
index 523210a4183e..d50d8fcae9da 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
@@ -65,6 +65,9 @@ class VEMCCodeEmitter : public MCCodeEmitter {
                              SmallVectorImpl<MCFixup> &Fixups,
                              const MCSubtargetInfo &STI) const;
 
+  uint64_t getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                                  SmallVectorImpl<MCFixup> &Fixups,
+                                  const MCSubtargetInfo &STI) const;
   uint64_t getCCOpValue(const MCInst &MI, unsigned OpNo,
                         SmallVectorImpl<MCFixup> &Fixups,
                         const MCSubtargetInfo &STI) const;
@@ -119,6 +122,19 @@ unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI,
   return 0;
 }
 
+uint64_t
+VEMCCodeEmitter::getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+                                        SmallVectorImpl<MCFixup> &Fixups,
+                                        const MCSubtargetInfo &STI) const {
+  const MCOperand &MO = MI.getOperand(OpNo);
+  if (MO.isReg() || MO.isImm())
+    return getMachineOpValue(MI, MO, Fixups, STI);
+
+  Fixups.push_back(
+      MCFixup::create(0, MO.getExpr(), (MCFixupKind)VE::fixup_ve_pc_lo32));
+  return 0;
+}
+
 uint64_t VEMCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned OpNo,
                                        SmallVectorImpl<MCFixup> &Fixups,
                                        const MCSubtargetInfo &STI) const {

diff  --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
index a7cb2ee527e2..a3ce3b3309be 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp
@@ -42,6 +42,7 @@ void VEMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
 bool VEMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) {
   switch (Kind) {
   case VK_VE_None:
+  case VK_VE_REFLONG:
     return false;
 
   case VK_VE_HI32:
@@ -58,7 +59,8 @@ bool VEMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) {
   case VK_VE_TLS_GD_LO32:
   case VK_VE_TPOFF_HI32:
   case VK_VE_TPOFF_LO32:
-    return false; // OS << "@<text>(";  break;
+    // Use suffix for these variant kinds
+    return false;
   }
   return true;
 }
@@ -66,6 +68,7 @@ bool VEMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) {
 void VEMCExpr::printVariantKindSuffix(raw_ostream &OS, VariantKind Kind) {
   switch (Kind) {
   case VK_VE_None:
+  case VK_VE_REFLONG:
     break;
   case VK_VE_HI32:
     OS << "@hi";
@@ -94,15 +97,15 @@ void VEMCExpr::printVariantKindSuffix(raw_ostream &OS, VariantKind Kind) {
   case VK_VE_PLT_HI32:
     OS << "@plt_hi";
     break;
+  case VK_VE_PLT_LO32:
+    OS << "@plt_lo";
+    break;
   case VK_VE_TLS_GD_HI32:
     OS << "@tls_gd_hi";
     break;
   case VK_VE_TLS_GD_LO32:
     OS << "@tls_gd_lo";
     break;
-  case VK_VE_PLT_LO32:
-    OS << "@plt_lo";
-    break;
   case VK_VE_TPOFF_HI32:
     OS << "@tpoff_hi";
     break;
@@ -135,6 +138,8 @@ VE::Fixups VEMCExpr::getFixupKind(VEMCExpr::VariantKind Kind) {
   switch (Kind) {
   default:
     llvm_unreachable("Unhandled VEMCExpr::VariantKind");
+  case VK_VE_REFLONG:
+    return VE::fixup_ve_reflong;
   case VK_VE_HI32:
     return VE::fixup_ve_hi32;
   case VK_VE_LO32:
@@ -159,6 +164,10 @@ VE::Fixups VEMCExpr::getFixupKind(VEMCExpr::VariantKind Kind) {
     return VE::fixup_ve_tls_gd_hi32;
   case VK_VE_TLS_GD_LO32:
     return VE::fixup_ve_tls_gd_lo32;
+  case VK_VE_TPOFF_HI32:
+    return VE::fixup_ve_tpoff_hi32;
+  case VK_VE_TPOFF_LO32:
+    return VE::fixup_ve_tpoff_lo32;
   }
 }
 
@@ -185,6 +194,8 @@ static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
   }
 
   case MCExpr::SymbolRef: {
+    // We're known to be under a TLS fixup, so any symbol should be
+    // modified. There should be only one.
     const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
     cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
     break;
@@ -201,5 +212,14 @@ void VEMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
 }
 
 void VEMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
+  switch (getKind()) {
+  default:
+    return;
+  case VK_VE_TLS_GD_HI32:
+  case VK_VE_TLS_GD_LO32:
+  case VK_VE_TPOFF_HI32:
+  case VK_VE_TPOFF_LO32:
+    break;
+  }
   fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
 }

diff  --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
index e2f6f2cb570a..2b0c44576099 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.h
@@ -24,6 +24,7 @@ class VEMCExpr : public MCTargetExpr {
 public:
   enum VariantKind {
     VK_VE_None,
+    VK_VE_REFLONG,
     VK_VE_HI32,
     VK_VE_LO32,
     VK_VE_PC_HI32,

diff  --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td
index f0850d97c2a4..8500f8ef1292 100644
--- a/llvm/lib/Target/VE/VEInstrInfo.td
+++ b/llvm/lib/Target/VE/VEInstrInfo.td
@@ -381,9 +381,8 @@ def MEMziHM : Operand<iPTR> {
 
 // Branch targets have OtherVT type.
 def brtarget32 : Operand<OtherVT> {
-}
-
-def calltarget : Operand<i64> {
+  let EncoderMethod = "getBranchTargetOpValue";
+  let DecoderMethod = "DecodeSIMM32";
 }
 
 // Operand for printing out a condition code.

diff  --git a/llvm/test/CodeGen/VE/symbol_relocation.ll b/llvm/test/CodeGen/VE/symbol_relocation.ll
new file mode 100644
index 000000000000..c6a142f4fdd4
--- /dev/null
+++ b/llvm/test/CodeGen/VE/symbol_relocation.ll
@@ -0,0 +1,30 @@
+; RUN: llc -filetype=obj -mtriple=ve -o - %s |  llvm-objdump - -d -r \
+; RUN:     | FileCheck %s
+; RUN: llc -filetype=obj -mtriple=ve -relocation-model=pic -o - %s \
+; RUN:     |  llvm-objdump - -d -r | FileCheck %s -check-prefix=PIC
+
+; CHECK:        lea %s0, 0
+; CHECK-NEXT:   R_VE_LO32 foo
+; CHECK-NEXT:   and %s0, %s0, (32)0
+; CHECK-NEXT:   lea.sl %s12, (, %s0)
+; CHECK-NEXT:   R_VE_HI32 foo
+; PIC:        lea %s15, (-24)
+; PIC-NEXT:   R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+; PIC-NEXT:   and %s15, %s15, (32)0
+; PIC-NEXT:   sic %s16
+; PIC-NEXT:   lea.sl %s15, (%s16, %s15)
+; PIC-NEXT:   R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+; PIC-NEXT:   lea %s12, (-24)
+; PIC-NEXT:   R_VE_PLT_LO32 foo
+; PIC-NEXT:   and %s12, %s12, (32)0
+; PIC-NEXT:   sic %s16
+; PIC-NEXT:   lea.sl %s12, (%s16, %s12)
+; PIC-NEXT:   R_VE_PLT_HI32 foo
+
+define i32 @main() {
+entry:
+  %call = call i32 @foo()
+  ret i32 %call
+}
+
+declare i32 @foo()

diff  --git a/llvm/test/CodeGen/VE/symbol_relocation_tls.ll b/llvm/test/CodeGen/VE/symbol_relocation_tls.ll
new file mode 100644
index 000000000000..702ed45efe18
--- /dev/null
+++ b/llvm/test/CodeGen/VE/symbol_relocation_tls.ll
@@ -0,0 +1,178 @@
+; FIXME: Even under non-pic mode, llvm for ve needs to generate pic code since
+;        nld doesn't work with non-pic code.  Thefore, we test only pic codes
+;        for both cases here.
+;      llc -filetype=obj -mtriple=ve -o - %s | llvm-objdump - -d -r \
+;          | FileCheck %s -check-prefix=LOCAL
+; RUN: llc -filetype=obj -mtriple=ve -o - %s | llvm-objdump - -d -r \
+; RUN:     | FileCheck %s -check-prefix=GENDYN
+; RUN: llc -filetype=obj -mtriple=ve -relocation-model=pic -o - %s \
+; RUN:     |  llvm-objdump - -d -r | FileCheck %s -check-prefix=GENDYNPIC
+
+ at x = external thread_local global i32, align 4
+ at y = internal thread_local global i32 0, align 4
+
+; Function Attrs: norecurse nounwind readnone
+define nonnull i32* @get_global() {
+; GENDYN:         lea %s0, (-24)
+; GENDYN-NEXT:    R_VE_TLS_GD_LO32 x
+; GENDYN-NEXT:    and %s0, %s0, (32)0
+; GENDYN-NEXT:    sic %s10
+; GENDYN-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYN-NEXT:    R_VE_TLS_GD_HI32 x
+; GENDYN-NEXT:    lea %s12, (8)
+; GENDYN-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYN-NEXT:    and %s12, %s12, (32)0
+; GENDYN-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYN-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYN-NEXT:    bsic %s10, (, %s12)
+; GENDYN-NEXT:    or %s11, 0, %s9
+;
+; GENDYNPIC:         lea %s15, (-24)
+; GENDYNPIC-NEXT:    R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    and %s15, %s15, (32)0
+; GENDYNPIC-NEXT:    sic %s16
+; GENDYNPIC-NEXT:    lea.sl %s15, (%s16, %s15)
+; GENDYNPIC-NEXT:    R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    lea %s0, (-24)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_LO32 x
+; GENDYNPIC-NEXT:    and %s0, %s0, (32)0
+; GENDYNPIC-NEXT:    sic %s10
+; GENDYNPIC-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_HI32 x
+; GENDYNPIC-NEXT:    lea %s12, (8)
+; GENDYNPIC-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYNPIC-NEXT:    and %s12, %s12, (32)0
+; GENDYNPIC-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYNPIC-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYNPIC-NEXT:    bsic %s10, (, %s12)
+; GENDYNPIC-NEXT:    or %s11, 0, %s9
+entry:
+  ret i32* @x
+}
+
+; Function Attrs: norecurse nounwind readnone
+define nonnull i32* @get_local() {
+; GENDYN:         lea %s0, (-24)
+; GENDYN-NEXT:    R_VE_TLS_GD_LO32 y
+; GENDYN-NEXT:    and %s0, %s0, (32)0
+; GENDYN-NEXT:    sic %s10
+; GENDYN-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYN-NEXT:    R_VE_TLS_GD_HI32 y
+; GENDYN-NEXT:    lea %s12, (8)
+; GENDYN-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYN-NEXT:    and %s12, %s12, (32)0
+; GENDYN-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYN-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYN-NEXT:    bsic %s10, (, %s12)
+; GENDYN-NEXT:    or %s11, 0, %s9
+;
+; GENDYNPIC:         lea %s15, (-24)
+; GENDYNPIC-NEXT:    R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    and %s15, %s15, (32)0
+; GENDYNPIC-NEXT:    sic %s16
+; GENDYNPIC-NEXT:    lea.sl %s15, (%s16, %s15)
+; GENDYNPIC-NEXT:    R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    lea %s0, (-24)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_LO32 y
+; GENDYNPIC-NEXT:    and %s0, %s0, (32)0
+; GENDYNPIC-NEXT:    sic %s10
+; GENDYNPIC-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_HI32 y
+; GENDYNPIC-NEXT:    lea %s12, (8)
+; GENDYNPIC-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYNPIC-NEXT:    and %s12, %s12, (32)0
+; GENDYNPIC-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYNPIC-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYNPIC-NEXT:    bsic %s10, (, %s12)
+; GENDYNPIC-NEXT:    or %s11, 0, %s9
+entry:
+  ret i32* @y
+}
+
+; Function Attrs: norecurse nounwind
+define void @set_global(i32 %v) {
+; GENDYN:         lea %s0, (-24)
+; GENDYN-NEXT:    R_VE_TLS_GD_LO32 x
+; GENDYN-NEXT:    and %s0, %s0, (32)0
+; GENDYN-NEXT:    sic %s10
+; GENDYN-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYN-NEXT:    R_VE_TLS_GD_HI32 x
+; GENDYN-NEXT:    lea %s12, (8)
+; GENDYN-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYN-NEXT:    and %s12, %s12, (32)0
+; GENDYN-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYN-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYN-NEXT:    bsic %s10, (, %s12)
+; GENDYN-NEXT:    stl %s18, (, %s0)
+; GENDYN-NEXT:    ld %s18, 48(, %s9)
+; GENDYN-NEXT:    or %s11, 0, %s9
+;
+; GENDYNPIC:         lea %s15, (-24)
+; GENDYNPIC-NEXT:    R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    and %s15, %s15, (32)0
+; GENDYNPIC-NEXT:    sic %s16
+; GENDYNPIC-NEXT:    lea.sl %s15, (%s16, %s15)
+; GENDYNPIC-NEXT:    R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    lea %s0, (-24)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_LO32 x
+; GENDYNPIC-NEXT:    and %s0, %s0, (32)0
+; GENDYNPIC-NEXT:    sic %s10
+; GENDYNPIC-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_HI32 x
+; GENDYNPIC-NEXT:    lea %s12, (8)
+; GENDYNPIC-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYNPIC-NEXT:    and %s12, %s12, (32)0
+; GENDYNPIC-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYNPIC-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYNPIC-NEXT:    bsic %s10, (, %s12)
+; GENDYNPIC-NEXT:    stl %s18, (, %s0)
+; GENDYNPIC-NEXT:    ld %s18, 48(, %s9)
+; GENDYNPIC-NEXT:    or %s11, 0, %s9
+entry:
+  store i32 %v, i32* @x, align 4
+  ret void
+}
+
+; Function Attrs: norecurse nounwind
+define void @set_local(i32 %v) {
+; GENDYN:         lea %s0, (-24)
+; GENDYN-NEXT:    R_VE_TLS_GD_LO32 y
+; GENDYN-NEXT:    and %s0, %s0, (32)0
+; GENDYN-NEXT:    sic %s10
+; GENDYN-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYN-NEXT:    R_VE_TLS_GD_HI32 y
+; GENDYN-NEXT:    lea %s12, (8)
+; GENDYN-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYN-NEXT:    and %s12, %s12, (32)0
+; GENDYN-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYN-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYN-NEXT:    bsic %s10, (, %s12)
+; GENDYN-NEXT:    stl %s18, (, %s0)
+; GENDYN-NEXT:    ld %s18, 48(, %s9)
+; GENDYN-NEXT:    or %s11, 0, %s9
+;
+; GENDYNPIC:         lea %s15, (-24)
+; GENDYNPIC-NEXT:    R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    and %s15, %s15, (32)0
+; GENDYNPIC-NEXT:    sic %s16
+; GENDYNPIC-NEXT:    lea.sl %s15, (%s16, %s15)
+; GENDYNPIC-NEXT:    R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+; GENDYNPIC-NEXT:    lea %s0, (-24)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_LO32 y
+; GENDYNPIC-NEXT:    and %s0, %s0, (32)0
+; GENDYNPIC-NEXT:    sic %s10
+; GENDYNPIC-NEXT:    lea.sl %s0, (%s10, %s0)
+; GENDYNPIC-NEXT:    R_VE_TLS_GD_HI32 y
+; GENDYNPIC-NEXT:    lea %s12, (8)
+; GENDYNPIC-NEXT:    R_VE_PLT_LO32 __tls_get_addr
+; GENDYNPIC-NEXT:    and %s12, %s12, (32)0
+; GENDYNPIC-NEXT:    lea.sl %s12, (%s10, %s12)
+; GENDYNPIC-NEXT:    R_VE_PLT_HI32 __tls_get_addr
+; GENDYNPIC-NEXT:    bsic %s10, (, %s12)
+; GENDYNPIC-NEXT:    stl %s18, (, %s0)
+; GENDYNPIC-NEXT:    ld %s18, 48(, %s9)
+; GENDYNPIC-NEXT:    or %s11, 0, %s9
+entry:
+  store i32 %v, i32* @y, align 4
+  ret void
+}

diff  --git a/llvm/test/MC/VE/sym-got.s b/llvm/test/MC/VE/sym-got.s
new file mode 100644
index 000000000000..0c0f93757d95
--- /dev/null
+++ b/llvm/test/MC/VE/sym-got.s
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve %s -o - | FileCheck %s
+# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | llvm-objdump -r - | FileCheck %s --check-prefix=CHECK-OBJ
+
+    lea %s15, _GLOBAL_OFFSET_TABLE_ at pc_lo(-24)
+    and %s15, %s15, (32)0
+    sic %s16
+    lea.sl %s15, _GLOBAL_OFFSET_TABLE_ at pc_hi(%s16, %s15)
+    lea %s0, dst at got_lo
+    and %s0, %s0, (32)0
+    lea.sl %s0, dst at got_hi(, %s0)
+    ld %s1, (%s0, %s15)
+# CHECK: lea %s15, _GLOBAL_OFFSET_TABLE_ at pc_lo(-24)
+# CHECK-NEXT: and %s15, %s15, (32)0
+# CHECK-NEXT: sic %s16
+# CHECK-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_ at pc_hi(%s16, %s15)
+# CHECK-NEXT: lea %s0, dst at got_lo
+# CHECK-NEXT: and %s0, %s0, (32)0
+# CHECK-NEXT: lea.sl %s0, dst at got_hi(, %s0)
+# CHECK-NEXT: ld %s1, (%s0, %s15)
+
+# CHECK-OBJ: 0 R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+# CHECK-OBJ-NEXT: 18 R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+# CHECK-OBJ-NEXT: 20 R_VE_GOT_LO32 dst
+# CHECK-OBJ-NEXT: 30 R_VE_GOT_HI32 dst

diff  --git a/llvm/test/MC/VE/sym-gotoff.s b/llvm/test/MC/VE/sym-gotoff.s
new file mode 100644
index 000000000000..bdd5e90aeaed
--- /dev/null
+++ b/llvm/test/MC/VE/sym-gotoff.s
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve %s -o - | FileCheck %s
+# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | llvm-objdump -r - | FileCheck %s --check-prefix=CHECK-OBJ
+
+    lea %s15, _GLOBAL_OFFSET_TABLE_ at pc_lo(-24)
+    and %s15, %s15, (32)0
+    sic %s16
+    lea.sl %s15, _GLOBAL_OFFSET_TABLE_ at pc_hi(%s16, %s15)
+    lea %s0, src at gotoff_lo
+    and %s0, %s0, (32)0
+    lea.sl %s0, src at gotoff_hi(, %s0)
+    ld1b.zx %s0, (%s0, %s15)
+# CHECK: lea %s15, _GLOBAL_OFFSET_TABLE_ at pc_lo(-24)
+# CHECK-NEXT: and %s15, %s15, (32)0
+# CHECK-NEXT: sic %s16
+# CHECK-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_ at pc_hi(%s16, %s15)
+# CHECK-NEXT: lea %s0, src at gotoff_lo
+# CHECK-NEXT: and %s0, %s0, (32)0
+# CHECK-NEXT: lea.sl %s0, src at gotoff_hi(, %s0)
+# CHECK-NEXT: ld1b.zx %s0, (%s0, %s15)
+
+# CHECK-OBJ: 0 R_VE_PC_LO32 _GLOBAL_OFFSET_TABLE_
+# CHECK-OBJ-NEXT: 18 R_VE_PC_HI32 _GLOBAL_OFFSET_TABLE_
+# CHECK-OBJ-NEXT: 20 R_VE_GOTOFF_LO32 src
+# CHECK-OBJ-NEXT: 30 R_VE_GOTOFF_HI32 src

diff  --git a/llvm/test/MC/VE/sym-tls.s b/llvm/test/MC/VE/sym-tls.s
new file mode 100644
index 000000000000..03a68cab5bb2
--- /dev/null
+++ b/llvm/test/MC/VE/sym-tls.s
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve %s -o - | FileCheck %s
+# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | llvm-objdump -r - | FileCheck %s --check-prefix=CHECK-OBJ
+
+    lea %s0, x at tls_gd_lo(-24)
+    and %s0, %s0, (32)0
+    sic %s10
+    lea.sl %s0, x at tls_gd_hi(%s10, %s0)
+    lea %s12, __tls_get_addr at plt_lo(8)
+    and %s12, %s12, (32)0
+    lea.sl %s12, __tls_get_addr at plt_hi(%s10, %s12)
+    bsic %s10, (, %s12)
+# CHECK: lea %s0, x at tls_gd_lo(-24)
+# CHECK-NEXT: and %s0, %s0, (32)0
+# CHECK-NEXT: sic %s10
+# CHECK-NEXT: lea.sl %s0, x at tls_gd_hi(%s10, %s0)
+# CHECK-NEXT: lea %s12, __tls_get_addr at plt_lo(8)
+# CHECK-NEXT: and %s12, %s12, (32)0
+# CHECK-NEXT: lea.sl %s12, __tls_get_addr at plt_hi(%s10, %s12)
+# CHECK-NEXT: bsic %s10, (, %s12)
+
+# CHECK-OBJ: 0 R_VE_TLS_GD_LO32 x
+# CHECK-OBJ-NEXT: 18 R_VE_TLS_GD_HI32 x
+# CHECK-OBJ-NEXT: 20 R_VE_PLT_LO32 __tls_get_addr
+# CHECK-OBJ-NEXT: 30 R_VE_PLT_HI32 __tls_get_addr

diff  --git a/llvm/test/MC/VE/sym-tpoff.s b/llvm/test/MC/VE/sym-tpoff.s
new file mode 100644
index 000000000000..bd0d08ce8bcc
--- /dev/null
+++ b/llvm/test/MC/VE/sym-tpoff.s
@@ -0,0 +1,14 @@
+# RUN: llvm-mc -triple=ve %s -o - | FileCheck %s
+# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | llvm-objdump -r - | FileCheck %s --check-prefix=CHECK-OBJ
+
+    lea %s34, x at tpoff_lo
+    and %s34, %s34, (32)0
+    lea.sl %s34, x at tpoff_hi(%s34)
+    adds.l %s0, %s14, %s34
+# CHECK: lea %s34, x at tpoff_lo
+# CHECK-NEXT: and %s34, %s34, (32)0
+# CHECK-NEXT: lea.sl %s34, x at tpoff_hi(%s34)
+# CHECK-NEXT: adds.l %s0, %s14, %s34
+
+# CHECK-OBJ: 0 R_VE_TPOFF_LO32 x
+# CHECK-OBJ-NEXT: 10 R_VE_TPOFF_HI32 x

diff  --git a/llvm/test/MC/VE/symbols.s b/llvm/test/MC/VE/symbols.s
new file mode 100644
index 000000000000..55702f89258c
--- /dev/null
+++ b/llvm/test/MC/VE/symbols.s
@@ -0,0 +1,15 @@
+# RUN: llvm-mc -triple=ve %s -o - | FileCheck %s
+# RUN: llvm-mc -triple=ve -filetype=obj %s -o - | llvm-objdump -r - | FileCheck %s --check-prefix=CHECK-OBJ
+
+        lea %s0, var
+        lea %s1, var at lo
+        and %s1, %s1, (32)0
+        lea.sl %s1, var at hi(, %s1)
+# CHECK: lea %s0, var
+# CHECK-NEXT: lea %s1, var at lo
+# CHECK-NEXT: and %s1, %s1, (32)0
+# CHECK-NEXT: lea.sl %s1, var at hi(, %s1)
+
+# CHECK-OBJ: 0 R_VE_REFLONG var
+# CHECK-OBJ-NEXT: 8 R_VE_LO32 var
+# CHECK-OBJ-NEXT: 18 R_VE_HI32 var


        


More information about the llvm-commits mailing list