From 2c9ed5d050b5c57bfed35bd82c23f46c714d10c0 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 30 Jan 2014 04:02:47 +0000 Subject: [PATCH] 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 --- include/llvm/MC/MCExpr.h | 1 + include/llvm/MC/MCStreamer.h | 3 ++ lib/MC/MCExpr.cpp | 1 + lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 27 ++++++++++++++ .../ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 3 ++ .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 19 ++++++++++ .../MC/ARM/directive-tlsdescseq-diagnostics.s | 35 +++++++++++++++++++ test/MC/ARM/directive-tlsdescseq.s | 33 +++++++++++++++++ 8 files changed, 122 insertions(+) create mode 100644 test/MC/ARM/directive-tlsdescseq-diagnostics.s create mode 100644 test/MC/ARM/directive-tlsdescseq.s diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 13f3ad0570b..133bd5280d7 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -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 diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 3eb5446f530..bb4adfcf862 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.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 diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index d402e6d896b..75bde8ed36b 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -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"; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 2f9a12f2c77..2b4eaf0f15c 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -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 X(TheARMTarget); diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index 5f719d5bb7c..d9a1453cc35 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -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: diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index efee318a047..c2e3503278b 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -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; diff --git a/test/MC/ARM/directive-tlsdescseq-diagnostics.s b/test/MC/ARM/directive-tlsdescseq-diagnostics.s new file mode 100644 index 00000000000..0d33b5894fe --- /dev/null +++ b/test/MC/ARM/directive-tlsdescseq-diagnostics.s @@ -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: ^ + diff --git a/test/MC/ARM/directive-tlsdescseq.s b/test/MC/ARM/directive-tlsdescseq.s new file mode 100644 index 00000000000..12db0589d7a --- /dev/null +++ b/test/MC/ARM/directive-tlsdescseq.s @@ -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 + -- 2.34.1