diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/MC/MCParser/ELFAsmParser.cpp | 72 | ||||
| -rw-r--r-- | llvm/test/MC/ELF/gnu-type-diagnostics.s | 18 | ||||
| -rw-r--r-- | llvm/test/MC/ELF/gnu-type-hash-diagnostics.s | 9 | ||||
| -rw-r--r-- | llvm/test/MC/ELF/gnu-type-hash.s | 16 | ||||
| -rw-r--r-- | llvm/test/MC/ELF/gnu-type.s | 38 |
5 files changed, 115 insertions, 38 deletions
diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp index 95c4971c52e..78bb6c7aad0 100644 --- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp +++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp @@ -561,6 +561,19 @@ bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { return false; } +static MCSymbolAttr MCAttrForString(StringRef Type) { + return StringSwitch<MCSymbolAttr>(Type) + .Cases("STT_FUNC", "function", MCSA_ELF_TypeFunction) + .Cases("STT_OBJECT", "object", MCSA_ELF_TypeObject) + .Cases("STT_TLS", "tls_object", MCSA_ELF_TypeTLS) + .Cases("STT_COMMON", "common", MCSA_ELF_TypeCommon) + .Cases("STT_NOTYPE", "notype", MCSA_ELF_TypeNoType) + .Cases("STT_GNU_IFUNC", "gnu_indirect_function", + MCSA_ELF_TypeIndFunction) + .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Default(MCSA_Invalid); +} + /// ParseDirectiveELFType /// ::= .type identifier , STT_<TYPE_IN_UPPER_CASE> /// ::= .type identifier , #attribute @@ -575,53 +588,36 @@ bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { // Handle the identifier as the key symbol. MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.type' directive"); - Lex(); - - StringRef Type; - SMLoc TypeLoc; - MCSymbolAttr Attr; - if (getLexer().is(AsmToken::Identifier)) { - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("STT_FUNC", MCSA_ELF_TypeFunction) - .Case("STT_OBJECT", MCSA_ELF_TypeObject) - .Case("STT_TLS", MCSA_ELF_TypeTLS) - .Case("STT_COMMON", MCSA_ELF_TypeCommon) - .Case("STT_NOTYPE", MCSA_ELF_TypeNoType) - .Case("STT_GNU_IFUNC", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); - } else if (getLexer().is(AsmToken::Hash) || getLexer().is(AsmToken::At) || - getLexer().is(AsmToken::Percent) || - getLexer().is(AsmToken::String)) { - if (!getLexer().is(AsmToken::String)) - Lex(); + // NOTE the comma is optional in all cases. It is only documented as being + // optional in the first case, however, GAS will silently treat the comma as + // optional in all cases. Furthermore, although the documentation states that + // the first form only accepts STT_<TYPE_IN_UPPER_CASE>, in reality, GAS + // accepts both the upper case name as well as the lower case aliases. + if (getLexer().is(AsmToken::Comma)) + Lex(); - TypeLoc = getLexer().getLoc(); - if (getParser().parseIdentifier(Type)) - return TokError("expected symbol type in directive"); - Attr = StringSwitch<MCSymbolAttr>(Type) - .Case("function", MCSA_ELF_TypeFunction) - .Case("object", MCSA_ELF_TypeObject) - .Case("tls_object", MCSA_ELF_TypeTLS) - .Case("common", MCSA_ELF_TypeCommon) - .Case("notype", MCSA_ELF_TypeNoType) - .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) - .Case("gnu_indirect_function", MCSA_ELF_TypeIndFunction) - .Default(MCSA_Invalid); - } else + if (getLexer().isNot(AsmToken::Identifier) && + getLexer().isNot(AsmToken::Hash) && getLexer().isNot(AsmToken::At) && + getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::String)) return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', " "'%<type>' or \"<type>\""); + if (getLexer().isNot(AsmToken::String) && + getLexer().isNot(AsmToken::Identifier)) + Lex(); + + SMLoc TypeLoc = getLexer().getLoc(); + + StringRef Type; + if (getParser().parseIdentifier(Type)) + return TokError("expected symbol type in directive"); + + MCSymbolAttr Attr = MCAttrForString(Type); if (Attr == MCSA_Invalid) return Error(TypeLoc, "unsupported attribute in '.type' directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.type' directive"); - Lex(); getStreamer().EmitSymbolAttribute(Sym, Attr); diff --git a/llvm/test/MC/ELF/gnu-type-diagnostics.s b/llvm/test/MC/ELF/gnu-type-diagnostics.s new file mode 100644 index 00000000000..df87d6df082 --- /dev/null +++ b/llvm/test/MC/ELF/gnu-type-diagnostics.s @@ -0,0 +1,18 @@ +// RUN: not llvm-mc -triple i686-elf -filetype asm -o /dev/null %s 2>&1 | FileCheck %s + + .type TYPE FUNC +// CHECK: error: unsupported attribute in '.type' directive +// CHECK: .type TYPE FUNC +// CHECK: ^ + + .type type stt_func +// CHECK: error: unsupported attribute in '.type' directive +// CHECK: .type type stt_func +// CHECK: ^ + + .type symbol 32 +// CHECK: error: expected STT_<TYPE_IN_UPPER_CASE>, '#<type>', '@<type>', '%<type>' or "<type>" +// CHECK: .type symbol 32 +// CHECK: ^ + + diff --git a/llvm/test/MC/ELF/gnu-type-hash-diagnostics.s b/llvm/test/MC/ELF/gnu-type-hash-diagnostics.s new file mode 100644 index 00000000000..eb364755c4d --- /dev/null +++ b/llvm/test/MC/ELF/gnu-type-hash-diagnostics.s @@ -0,0 +1,9 @@ +@ RUN: not llvm-mc -triple arm-elf -filetype asm -o /dev/null %s 2>&1 | FileCheck %s + + .syntax unified + + .type TYPE #32 +// CHECK: error: expected symbol type in directive +// CHECK: .type TYPE #32 +// CHECK: ^ + diff --git a/llvm/test/MC/ELF/gnu-type-hash.s b/llvm/test/MC/ELF/gnu-type-hash.s new file mode 100644 index 00000000000..ae5c47c567c --- /dev/null +++ b/llvm/test/MC/ELF/gnu-type-hash.s @@ -0,0 +1,16 @@ +@ RUN: llvm-mc -triple arm-elf -filetype asm -o - %s | FileCheck %s + + .syntax unified + + .type TYPE #STT_FUNC +// CHECK: .type TYPE,%function + + .type type #function +// CHECK: .type type,%function + + .type comma_TYPE, #STT_FUNC +// CHECK: .type comma_TYPE,%function + + .type comma_type, #function +// CHECK: .type comma_type,%function + diff --git a/llvm/test/MC/ELF/gnu-type.s b/llvm/test/MC/ELF/gnu-type.s new file mode 100644 index 00000000000..19029e48ee9 --- /dev/null +++ b/llvm/test/MC/ELF/gnu-type.s @@ -0,0 +1,38 @@ +// RUN: llvm-mc -triple i686-elf -filetype asm -o - %s | FileCheck %s + + .type TYPE STT_FUNC +// CHECK: .type TYPE,@function + + .type comma_TYPE, STT_FUNC +// CHECK: .type comma_TYPE,@function + + .type at_TYPE, @STT_FUNC +// CHECK: .type at_TYPE,@function + + .type percent_TYPE, %STT_FUNC +// CHECK: .type percent_TYPE,@function + + .type string_TYPE, "STT_FUNC" +// CHECK: .type string_TYPE,@function + + .type type function +// CHECK: .type type,@function + + .type comma_type, function +// CHECK: .type comma_type,@function + + .type at_type, @function +// CHECK: .type at_type,@function + + .type percent_type, %function +// CHECK: .type percent_type,@function + + .type string_type, "function" +// CHECK: .type string_type,@function + + .type special gnu_unique_object +// CHECK: .type special,@gnu_unique_object + + .type comma_special, gnu_unique_object +// CHECK: .type comma_special,@gnu_unique_object + |

