mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-23 12:45:47 +00:00
ARM: suuport .tlsdescseq directive
This enhances the ARMAsmParser to handle .tlsdescseq directives. This is a slightly special relocation. We must be able to generate them, but not consume them in assembly. The relocation is meant to assist the linker in generating a TLS descriptor sequence. The ELF target streamer is enhanced to append additional fixups into the current segment and that is used to emit the new R_ARM_TLS_DESCSEQ relocations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200448 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4747d6b0a5
commit
2c9ed5d050
@ -168,6 +168,7 @@ public:
|
||||
VK_ARM_TLSLDO, // symbol(tlsldo)
|
||||
VK_ARM_TLSCALL, // symbol(tlscall)
|
||||
VK_ARM_TLSDESC, // symbol(tlsdesc)
|
||||
VK_ARM_TLSDESCSEQ,
|
||||
|
||||
VK_PPC_LO, // symbol@l
|
||||
VK_PPC_HI, // symbol@h
|
||||
|
@ -33,6 +33,7 @@ class MCInstPrinter;
|
||||
class MCSection;
|
||||
class MCStreamer;
|
||||
class MCSymbol;
|
||||
class MCSymbolRefExpr;
|
||||
class MCSubtargetInfo;
|
||||
class StringRef;
|
||||
class Twine;
|
||||
@ -107,6 +108,8 @@ public:
|
||||
virtual void emitArch(unsigned Arch) = 0;
|
||||
virtual void finishAttributeSection() = 0;
|
||||
virtual void emitInst(uint32_t Inst, char Suffix = '\0') = 0;
|
||||
|
||||
virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) = 0;
|
||||
};
|
||||
|
||||
/// MCStreamer - Streaming machine code generation interface. This interface
|
||||
|
@ -187,6 +187,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
|
||||
case VK_ARM_TLSLDO: return "tlsldo";
|
||||
case VK_ARM_TLSCALL: return "tlscall";
|
||||
case VK_ARM_TLSDESC: return "tlsdesc";
|
||||
case VK_ARM_TLSDESCSEQ: return "tlsdescseq";
|
||||
case VK_PPC_LO: return "l";
|
||||
case VK_PPC_HI: return "h";
|
||||
case VK_PPC_HA: return "ha";
|
||||
|
@ -296,6 +296,7 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||
bool parseDirectiveEven(SMLoc L);
|
||||
bool parseDirectivePersonalityIndex(SMLoc L);
|
||||
bool parseDirectiveUnwindRaw(SMLoc L);
|
||||
bool parseDirectiveTLSDescSeq(SMLoc L);
|
||||
|
||||
StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
|
||||
bool &CarrySetting, unsigned &ProcessorIMod,
|
||||
@ -8084,6 +8085,8 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
return parseDirectivePersonalityIndex(DirectiveID.getLoc());
|
||||
else if (IDVal == ".unwind_raw")
|
||||
return parseDirectiveUnwindRaw(DirectiveID.getLoc());
|
||||
else if (IDVal == ".tlsdescseq")
|
||||
return parseDirectiveTLSDescSeq(DirectiveID.getLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9001,6 +9004,30 @@ bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// parseDirectiveTLSDescSeq
|
||||
/// ::= .tlsdescseq tls-variable
|
||||
bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) {
|
||||
if (getLexer().isNot(AsmToken::Identifier)) {
|
||||
TokError("expected variable after '.tlsdescseq' directive");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
|
||||
const MCSymbolRefExpr *SRE =
|
||||
MCSymbolRefExpr::Create(Parser.getTok().getIdentifier(),
|
||||
MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext());
|
||||
Lex();
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
Error(Parser.getTok().getLoc(), "unexpected token");
|
||||
Parser.eatToEndOfStatement();
|
||||
return false;
|
||||
}
|
||||
|
||||
getTargetStreamer().AnnotateTLSDescriptorSequence(SRE);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Force static initialization.
|
||||
extern "C" void LLVMInitializeARMAsmParser() {
|
||||
RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
|
||||
|
@ -269,6 +269,9 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
|
||||
case MCSymbolRefExpr::VK_ARM_TLSDESC:
|
||||
Type = ELF::R_ARM_TLS_GOTDESC;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_ARM_TLSDESCSEQ:
|
||||
Type = ELF::R_ARM_TLS_DESCSEQ;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ARM::fixup_arm_ldst_pcrel_12:
|
||||
|
@ -139,6 +139,8 @@ class ARMTargetAsmStreamer : public ARMTargetStreamer {
|
||||
virtual void emitInst(uint32_t Inst, char Suffix = '\0');
|
||||
virtual void finishAttributeSection();
|
||||
|
||||
virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE);
|
||||
|
||||
public:
|
||||
ARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS,
|
||||
MCInstPrinter &InstPrinter, bool VerboseAsm);
|
||||
@ -241,6 +243,10 @@ void ARMTargetAsmStreamer::emitFPU(unsigned FPU) {
|
||||
}
|
||||
void ARMTargetAsmStreamer::finishAttributeSection() {
|
||||
}
|
||||
void
|
||||
ARMTargetAsmStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) {
|
||||
OS << "\t.tlsdescseq\t" << S->getSymbol().getName();
|
||||
}
|
||||
|
||||
void ARMTargetAsmStreamer::emitInst(uint32_t Inst, char Suffix) {
|
||||
OS << "\t.inst";
|
||||
@ -397,6 +403,8 @@ private:
|
||||
virtual void emitInst(uint32_t Inst, char Suffix = '\0');
|
||||
virtual void finishAttributeSection();
|
||||
|
||||
virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE);
|
||||
|
||||
size_t calculateContentSize() const;
|
||||
|
||||
public:
|
||||
@ -605,6 +613,8 @@ private:
|
||||
void SwitchToExTabSection(const MCSymbol &FnStart);
|
||||
void SwitchToExIdxSection(const MCSymbol &FnStart);
|
||||
|
||||
void EmitFixup(const MCExpr *Expr, MCFixupKind Kind);
|
||||
|
||||
bool IsThumb;
|
||||
int64_t MappingSymbolCounter;
|
||||
|
||||
@ -953,6 +963,10 @@ void ARMTargetELFStreamer::finishAttributeSection() {
|
||||
Contents.clear();
|
||||
FPU = ARM::INVALID_FPU;
|
||||
}
|
||||
void
|
||||
ARMTargetELFStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *S) {
|
||||
getStreamer().EmitFixup(S, FK_Data_4);
|
||||
}
|
||||
void ARMTargetELFStreamer::emitInst(uint32_t Inst, char Suffix) {
|
||||
getStreamer().emitInst(Inst, Suffix);
|
||||
}
|
||||
@ -1011,6 +1025,11 @@ inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
|
||||
SectionKind::getDataRel(),
|
||||
FnStart);
|
||||
}
|
||||
void ARMELFStreamer::EmitFixup(const MCExpr *Expr, MCFixupKind Kind) {
|
||||
MCDataFragment *Frag = getOrCreateDataFragment();
|
||||
Frag->getFixups().push_back(MCFixup::Create(Frag->getContents().size(), Expr,
|
||||
Kind));
|
||||
}
|
||||
|
||||
void ARMELFStreamer::Reset() {
|
||||
ExTab = NULL;
|
||||
|
35
test/MC/ARM/directive-tlsdescseq-diagnostics.s
Normal file
35
test/MC/ARM/directive-tlsdescseq-diagnostics.s
Normal file
@ -0,0 +1,35 @@
|
||||
@ RUN: not llvm-mc -triple armv7-linux-gnu -filetype asm -o /dev/null %s 2>&1 \
|
||||
@ RUN: | FileCheck %s
|
||||
|
||||
.type missing_variable,%function
|
||||
missing_variable:
|
||||
.tlsdescseq
|
||||
|
||||
@ CHECK: error: expected variable after '.tlsdescseq' directive
|
||||
@ CHECK: .tlsdescseq
|
||||
@ CHECK: ^
|
||||
|
||||
.type bad_expression,%function
|
||||
bad_expression:
|
||||
.tlsdescseq variable(tlsdesc)
|
||||
|
||||
@ CHECK: error: unexpected token
|
||||
@ CHECK: .tlsdescseq variable(tlsdesc)
|
||||
@ CHECK: ^
|
||||
|
||||
.type trailing_garbage,%function
|
||||
trailing_garbage:
|
||||
.tlsdescseq variable,
|
||||
|
||||
@ CHECK: error: unexpected token
|
||||
@ CHECK: .tlsdescseq variable,
|
||||
@ CHECK: ^
|
||||
|
||||
.type invalid_use,%function
|
||||
invalid_use:
|
||||
blx invalid(tlsdescseq)
|
||||
|
||||
@ CHECK: error: invalid variant 'tlsdescseq'
|
||||
@ CHECK: blx invalid(tlsdescseq)
|
||||
@ CHECK: ^
|
||||
|
33
test/MC/ARM/directive-tlsdescseq.s
Normal file
33
test/MC/ARM/directive-tlsdescseq.s
Normal file
@ -0,0 +1,33 @@
|
||||
@ RUN: llvm-mc -triple armv7-linux-gnu -filetype obj -o - %s | llvm-readobj -r \
|
||||
@ RUN: | FileCheck %s
|
||||
@ RUN: llvm-mc -triple armv7-linux-gnu -filetype asm -o - %s \
|
||||
@ RUN: | FileCheck -check-prefix CHECK-ASM %s
|
||||
|
||||
.type tlsdescseq,%function
|
||||
tlsdescseq:
|
||||
ldr r1, [pc, #8]
|
||||
1:
|
||||
.tlsdescseq variable
|
||||
add r2, pc, r1
|
||||
.tlsdescseq variable
|
||||
ldr r3, [r1, #4]
|
||||
.tlsdescseq variable
|
||||
blx r3
|
||||
2:
|
||||
.word variable(tlsdesc) + (. - 1b)
|
||||
|
||||
@ CHECK: Relocations [
|
||||
@ CHECK: 0x4 R_ARM_TLS_DESCSEQ variable 0x0
|
||||
@ CHECK: 0x8 R_ARM_TLS_DESCSEQ variable 0x0
|
||||
@ CHECK: 0xC R_ARM_TLS_DESCSEQ variable 0x0
|
||||
@ CHECK: 0x10 R_ARM_TLS_GOTDESC variable 0x0
|
||||
@ CHECK: ]
|
||||
|
||||
@ CHECK-ASM: ldr r1, [pc, #8]
|
||||
@ CHECK-ASM: .tlsdescseq variable
|
||||
@ CHECK-ASM: add r2, pc, r1
|
||||
@ CHECK-ASM: .tlsdescseq variable
|
||||
@ CHECK-ASM: ldr r3, [r1, #4]
|
||||
@ CHECK-ASM: .tlsdescseq variable
|
||||
@ CHECK-ASM: blx r3
|
||||
|
Loading…
x
Reference in New Issue
Block a user