diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index f556d6237ff..b62252057f9 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -166,6 +166,7 @@ public: VK_ARM_TARGET2, VK_ARM_PREL31, VK_ARM_TLSLDO, // symbol(tlsldo) + VK_ARM_TLSCALL, // symbol(tlscall) VK_PPC_LO, // symbol@l VK_PPC_HI, // symbol@h diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 2052d55dc7e..3772bceea57 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -185,6 +185,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_ARM_TARGET2: return "target2"; case VK_ARM_PREL31: return "prel31"; case VK_ARM_TLSLDO: return "tlsldo"; + case VK_ARM_TLSCALL: return "tlscall"; case VK_PPC_LO: return "l"; case VK_PPC_HI: return "h"; case VK_PPC_HA: return "ha"; @@ -408,6 +409,8 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) { .Case("prel31", VK_ARM_PREL31) .Case("TLSLDO", VK_ARM_TLSLDO) .Case("tlsldo", VK_ARM_TLSLDO) + .Case("TLSCALL", VK_ARM_TLSCALL) + .Case("tlscall", VK_ARM_TLSCALL) .Default(VK_Invalid); } diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 305c7587cb1..7db700472cb 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -380,6 +380,9 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case ARM::fixup_arm_blx: // These values don't encode the low two bits since they're always zero. // Offset by 8 just as above. + if (const MCSymbolRefExpr *SRE = dyn_cast(Fixup.getValue())) + if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) + return 0; return 0xffffff & ((Value - 8) >> 2); case ARM::fixup_t2_uncondbranch: { Value = Value - 4; @@ -461,6 +464,9 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Note that the halfwords are stored high first, low second; so we need // to transpose the fixup value here to map properly. uint32_t offset = (Value - 2) >> 2; + if (const MCSymbolRefExpr *SRE = dyn_cast(Fixup.getValue())) + if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_TLSCALL) + offset = 0; uint32_t signBit = (offset & 0x400000) >> 22; uint32_t I1Bit = (offset & 0x200000) >> 21; uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index 6fcc021a6c7..08c040235fd 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -179,6 +179,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_PLT: Type = ELF::R_ARM_PLT32; break; + case MCSymbolRefExpr::VK_ARM_TLSCALL: + Type = ELF::R_ARM_TLS_CALL; + break; default: Type = ELF::R_ARM_CALL; break; @@ -211,7 +214,14 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, break; case ARM::fixup_arm_thumb_bl: case ARM::fixup_arm_thumb_blx: - Type = ELF::R_ARM_THM_CALL; + switch (Modifier) { + case MCSymbolRefExpr::VK_ARM_TLSCALL: + Type = ELF::R_ARM_THM_TLS_CALL; + break; + default: + Type = ELF::R_ARM_THM_CALL; + break; + } break; } } else { @@ -253,6 +263,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, case MCSymbolRefExpr::VK_ARM_TLSLDO: Type = ELF::R_ARM_TLS_LDO32; break; + case MCSymbolRefExpr::VK_ARM_TLSCALL: + Type = ELF::R_ARM_TLS_CALL; + break; } break; case ARM::fixup_arm_ldst_pcrel_12: diff --git a/test/MC/ARM/symbol-variants.s b/test/MC/ARM/symbol-variants.s index 1ab504cf655..f0bf4c4b7c0 100644 --- a/test/MC/ARM/symbol-variants.s +++ b/test/MC/ARM/symbol-variants.s @@ -70,3 +70,10 @@ bl f05(plt) .word f21(tlsldo) @CHECK: 80 R_ARM_TLS_LDO32 f20 @CHECK: 84 R_ARM_TLS_LDO32 f21 + +@ tlscall +.word f22(TLSCALL) +.word f23(tlscall) +@ CHECK: 88 R_ARM_TLS_CALL f22 +@ CHECK: 92 R_ARM_TLS_CALL f23 +