diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index a97b450a46d..1b3ab577519 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -30,7 +30,6 @@ class AsmLexer : public MCAsmLexer { const char *CurPtr; const MemoryBuffer *CurBuf; bool isAtStartOfLine; - bool AllowAtInIdentifier; // Cached here to avoid repeated MAI query. void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; AsmLexer(const AsmLexer&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index 53b380f12f7..8edf3a4423f 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -118,6 +118,7 @@ class MCAsmLexer { protected: // Can only create subclasses. const char *TokStart; bool SkipSpace; + bool AllowAtInIdentifier; MCAsmLexer(); @@ -170,6 +171,9 @@ public: /// setSkipSpace - Set whether spaces should be ignored by the lexer void setSkipSpace(bool val) { SkipSpace = val; } + + bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } + void setAllowAtInIdentifier(bool v) { AllowAtInIdentifier = v; } }; } // End llvm namespace diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 8807975e854..ca5532d4851 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -590,7 +590,14 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { if (getLexer().isNot(AsmToken::Comma)) return TokError("expected a comma"); + // ARM assembly uses @ for a comment... + // except when parsing the second parameter of the .symver directive. + // Force the next symbol to allow @ in the identifier, which is + // required for this directive and then reset it to its initial state. + const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier(); + getLexer().setAllowAtInIdentifier(true); Lex(); + getLexer().setAllowAtInIdentifier(AllowAtInIdentifier); StringRef AliasName; if (getParser().parseIdentifier(AliasName)) diff --git a/test/MC/ARM/arm-elf-symver.s b/test/MC/ARM/arm-elf-symver.s new file mode 100644 index 00000000000..0d141b7fd8a --- /dev/null +++ b/test/MC/ARM/arm-elf-symver.s @@ -0,0 +1,152 @@ +@ RUN: llvm-mc -filetype=obj -triple arm-none-linux-gnueabi %s -o - | llvm-readobj -r -t | FileCheck %s +@ RUN: llvm-mc -filetype=obj -triple thumb-none-linux-gnueabi %s -o - | llvm-readobj -r -t | FileCheck %s + +defined1: +defined2: +defined3: + .symver defined1, bar1@zed + .symver undefined1, bar2@zed + + .symver defined2, bar3@@zed + + .symver defined3, bar5@@@zed + .symver undefined3, bar6@@@zed + + .long defined1 + .long undefined1 + .long defined2 + .long defined3 + .long undefined3 + + .global global1 + .symver global1, g1@@zed +global1: + +@ CHECK: Relocations [ +@ CHECK-NEXT: Section (2) .rel.text { +@ CHECK-NEXT: 0x0 R_ARM_ABS32 defined1 0x0 +@ CHECK-NEXT: 0x4 R_ARM_ABS32 bar2@zed 0x0 +@ CHECK-NEXT: 0x8 R_ARM_ABS32 defined2 0x0 +@ CHECK-NEXT: 0xC R_ARM_ABS32 defined3 0x0 +@ CHECK-NEXT: 0x10 R_ARM_ABS32 bar6@zed 0x0 +@ CHECK-NEXT: } +@ CHECK-NEXT: ] + +@ CHECK: Symbol { +@ CHECK: Name: bar1@zed (28) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: bar3@@zed (46) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: bar5@@zed (56) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: defined1 (1) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: defined2 (10) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: defined3 (19) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: .text (0) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: Section (0x3) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: .data (0) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: Section (0x3) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .data (0x3) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: .bss (0) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Local (0x0) +@ CHECK-NEXT: Type: Section (0x3) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .bss (0x4) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: g1@@zed (88) +@ CHECK-NEXT: Value: 0x14 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Global (0x1) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: global1 (80) +@ CHECK-NEXT: Value: 0x14 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Global (0x1) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: .text (0x1) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: bar2@zed (37) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Global (0x1) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: (0x0) +@ CHECK-NEXT: } +@ CHECK-NEXT: Symbol { +@ CHECK-NEXT: Name: bar6@zed (66) +@ CHECK-NEXT: Value: 0x0 +@ CHECK-NEXT: Size: 0 +@ CHECK-NEXT: Binding: Global (0x1) +@ CHECK-NEXT: Type: None (0x0) +@ CHECK-NEXT: Other: 0 +@ CHECK-NEXT: Section: (0x0) +@ CHECK-NEXT: } +@ CHECK-NEXT: ] diff --git a/test/MC/ARM/comment.s b/test/MC/ARM/comment.s index e95f313aca2..c24bc1aaa40 100644 --- a/test/MC/ARM/comment.s +++ b/test/MC/ARM/comment.s @@ -9,6 +9,18 @@ foo: .long baz@got add r0, r0@ignore this extra junk +@ the symver directive should allow @ in the second symbol name +defined1: +defined2: +defined3: +bar: + .symver defined1, bar1@zed + .symver defined2, bar3@@zed + .symver defined3, bar5@@@zed + +far: + .long baz@got + @CHECK-LABEL: foo: @CHECK: bl boo @CHECK-NOT: @ @@ -21,4 +33,15 @@ foo: @CHECK: add r0, r0 @CHECK-NOT: @ +@CHECK-LABEL: bar: +@CHECK: bar1@zed = defined1 +@CHECK: bar3@@zed = defined2 +@CHECK: bar5@@@zed = defined3 + +@ Make sure we did not mess up the parser state and it still lexes +@ comments correctly by excluding the @ in normal symbols +@CHECK-LABEL: far: +@CHECK: .long baz +@CHECK-NOT: @ + @ERROR-NOT: error: